diff --git a/Client/mods/deathmatch/CVoiceRecorder.cpp b/Client/mods/deathmatch/CVoiceRecorder.cpp index bf87136f2fd..be3ec3f1d7d 100644 --- a/Client/mods/deathmatch/CVoiceRecorder.cpp +++ b/Client/mods/deathmatch/CVoiceRecorder.cpp @@ -206,7 +206,7 @@ void CVoiceRecorder::SetPTTState(bool bState) { m_Mutex.unlock(); CLuaArguments Arguments; - bool bEventTriggered = g_pClientGame->GetLocalPlayer()->CallEvent("onClientPlayerVoiceStart", Arguments, true); + bool bEventTriggered = g_pClientGame->GetLocalPlayer()->CallEvent(BuiltInEvents::onClientPlayerVoiceStart, Arguments, true); if (!bEventTriggered) return; @@ -229,7 +229,7 @@ void CVoiceRecorder::SetPTTState(bool bState) { m_Mutex.unlock(); CLuaArguments Arguments; - g_pClientGame->GetLocalPlayer()->CallEvent("onClientPlayerVoiceStop", Arguments, true); + g_pClientGame->GetLocalPlayer()->CallEvent(BuiltInEvents::onClientPlayerVoiceStop, Arguments, true); return; } } diff --git a/Client/mods/deathmatch/ClientCommands.cpp b/Client/mods/deathmatch/ClientCommands.cpp index 8c87270fb37..2b3693f1ec1 100644 --- a/Client/mods/deathmatch/ClientCommands.cpp +++ b/Client/mods/deathmatch/ClientCommands.cpp @@ -73,7 +73,7 @@ bool COMMAND_Executed(const char* szCommand, const char* szArguments, bool bHand Arguments.PushString(strClumpedCommand); } - pLocalPlayer->CallEvent("onClientConsole", Arguments, true); + pLocalPlayer->CallEvent(BuiltInEvents::onClientConsole, Arguments, true); } // Write the chatlength and the content diff --git a/Client/mods/deathmatch/StdInc.h b/Client/mods/deathmatch/StdInc.h index 143e7a3498d..0aac763764c 100644 --- a/Client/mods/deathmatch/StdInc.h +++ b/Client/mods/deathmatch/StdInc.h @@ -95,7 +95,6 @@ #include #include #include -#include #include #include #include @@ -154,7 +153,6 @@ // Deathmatch includes #include "ClientCommands.h" #include "CClient.h" -#include "CEvents.h" #include "HeapTrace.h" #include "logic/CClientGame.h" #include "logic/CClientModelCacheManager.h" diff --git a/Client/mods/deathmatch/logic/CClientColManager.cpp b/Client/mods/deathmatch/logic/CClientColManager.cpp index bb1050b54bb..b67ce9aa688 100644 --- a/Client/mods/deathmatch/logic/CClientColManager.cpp +++ b/Client/mods/deathmatch/logic/CClientColManager.cpp @@ -152,12 +152,12 @@ void CClientColManager::HandleHitDetectionResult(bool bHit, CClientColShape* pSh CLuaArguments Arguments; Arguments.PushElement(pEntity); Arguments.PushBoolean((pShape->GetDimension() == pEntity->GetDimension())); - pShape->CallEvent("onClientColShapeHit", Arguments, true); + pShape->CallEvent(BuiltInEvents::onClientColShapeHit, Arguments, true); CLuaArguments Arguments2; Arguments2.PushElement(pShape); Arguments2.PushBoolean((pShape->GetDimension() == pEntity->GetDimension())); - pEntity->CallEvent("onClientElementColShapeHit", Arguments2, true); + pEntity->CallEvent(BuiltInEvents::onClientElementColShapeHit, Arguments2, true); } // Run whatever callback the collision item might have attached @@ -177,12 +177,12 @@ void CClientColManager::HandleHitDetectionResult(bool bHit, CClientColShape* pSh CLuaArguments Arguments; Arguments.PushElement(pEntity); Arguments.PushBoolean((pShape->GetDimension() == pEntity->GetDimension())); - pShape->CallEvent("onClientColShapeLeave", Arguments, true); + pShape->CallEvent(BuiltInEvents::onClientColShapeLeave, Arguments, true); CLuaArguments Arguments2; Arguments2.PushElement(pShape); Arguments2.PushBoolean((pShape->GetDimension() == pEntity->GetDimension())); - pEntity->CallEvent("onClientElementColShapeLeave", Arguments2, true); + pEntity->CallEvent(BuiltInEvents::onClientElementColShapeLeave, Arguments2, true); pShape->CallLeaveCallback(*pEntity); } diff --git a/Client/mods/deathmatch/logic/CClientEntity.cpp b/Client/mods/deathmatch/logic/CClientEntity.cpp index 61be4ca269d..9a638f338c8 100644 --- a/Client/mods/deathmatch/logic/CClientEntity.cpp +++ b/Client/mods/deathmatch/logic/CClientEntity.cpp @@ -9,6 +9,7 @@ *****************************************************************************/ #include "StdInc.h" +#include using std::list; @@ -41,7 +42,6 @@ CClientEntity::CClientEntity(ElementID ID) : ClassInit(this) CElementIDs::SetElement(ID, this); m_pCustomData = new CCustomData; - m_pEventManager = new CMapEventManager; m_pAttachedToEntity = NULL; @@ -101,12 +101,6 @@ CClientEntity::~CClientEntity() RemoveAllCollisions(); - if (m_pEventManager) - { - delete m_pEventManager; - m_pEventManager = NULL; - } - if (m_pElementGroup) { m_pElementGroup->Remove(this); @@ -484,7 +478,7 @@ void CClientEntity::SetCustomData(const char* szName, const CLuaArgument& Variab Arguments.PushString(szName); Arguments.PushArgument(oldVariable); Arguments.PushArgument(Variable); - CallEvent("onClientElementDataChange", Arguments, true); + CallEvent(BuiltInEvents::onClientElementDataChange, Arguments, true); } void CClientEntity::DeleteCustomData(const char* szName) @@ -504,7 +498,7 @@ void CClientEntity::DeleteCustomData(const char* szName) Arguments.PushString(szName); Arguments.PushArgument(oldVariable); Arguments.PushArgument(CLuaArgument()); // Use nil as the new value to indicate the data has been removed - CallEvent("onClientElementDataChange", Arguments, true); + CallEvent(BuiltInEvents::onClientElementDataChange, Arguments, true); } } @@ -604,7 +598,7 @@ void CClientEntity::SetDimension(unsigned short usDimension) CLuaArguments Arguments; Arguments.PushNumber(usOldDimension); Arguments.PushNumber(usDimension); - CallEvent("onClientElementDimensionChange", Arguments, true); + CallEvent(BuiltInEvents::onClientElementDimensionChange, Arguments, true); } bool CClientEntity::IsOutOfBounds() @@ -724,104 +718,15 @@ void CClientEntity::SetAttachedOffsets(CVector& vecPosition, CVector& vecRotatio m_vecAttachedRotation = vecRotation; } -bool CClientEntity::AddEvent(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction, bool bPropagated, EEventPriorityType eventPriority, - float fPriorityMod) -{ - return m_pEventManager->Add(pLuaMain, szName, iLuaFunction, bPropagated, eventPriority, fPriorityMod); -} - -bool CClientEntity::CallEvent(const char* szName, const CLuaArguments& Arguments, bool bCallOnChildren) -{ - if (!g_pClientGame->GetDebugHookManager()->OnPreEvent(szName, Arguments, this, NULL)) - return false; - - TIMEUS startTime = GetTimeUs(); - - CEvents* pEvents = g_pClientGame->GetEvents(); - - // Make sure our event-manager knows we're about to call an event - pEvents->PreEventPulse(); - - // Call the event on our parents/us first - CallParentEvent(szName, Arguments, this); - - if (bCallOnChildren) - { - // Call it on all our children - CallEventNoParent(szName, Arguments, this); - } - - // Tell the event manager that we're done calling the event - pEvents->PostEventPulse(); - - if (IS_TIMING_CHECKPOINTS()) - { - TIMEUS deltaTimeUs = GetTimeUs() - startTime; - if (deltaTimeUs > 10000) - TIMING_DETAIL(SString("Event: %s [%d ms]", szName, deltaTimeUs / 1000)); - } - - g_pClientGame->GetDebugHookManager()->OnPostEvent(szName, Arguments, this, NULL); - - // Return whether it got cancelled or not - return (!pEvents->WasEventCancelled()); -} - -void CClientEntity::CallEventNoParent(const char* szName, const CLuaArguments& Arguments, CClientEntity* pSource) -{ - // Call it on us if this isn't the same class it was raised on - // TODO not sure why the null check is necessary (eAi) - if (pSource != this && m_pEventManager != NULL && m_pEventManager->HasEvents()) - { - m_pEventManager->Call(szName, Arguments, pSource, this); - } - - // Call it on all our children - if (!m_Children.empty()) - { - CElementListSnapshot* pList = GetChildrenListSnapshot(); - pList->AddRef(); // Keep list alive during use - for (CElementListSnapshot::const_iterator iter = pList->begin(); iter != pList->end(); iter++) - { - CClientEntity* pEntity = *iter; - if (!pEntity->IsBeingDeleted()) - { - if (!pEntity->m_pEventManager || pEntity->m_pEventManager->HasEvents() || !pEntity->m_Children.empty()) - { - pEntity->CallEventNoParent(szName, Arguments, pSource); - if (m_bBeingDeleted) - break; - } - } - } - pList->Release(); - } -} - -void CClientEntity::CallParentEvent(const char* szName, const CLuaArguments& Arguments, CClientEntity* pSource) -{ - // Call the event on us - if (m_pEventManager && m_pEventManager->HasEvents()) - { - m_pEventManager->Call(szName, Arguments, pSource, this); - } - - // Call parent's handler - if (m_pParent) - { - m_pParent->CallParentEvent(szName, Arguments, pSource); - } -} - -bool CClientEntity::DeleteEvent(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction) +bool CClientEntity::CallEvent(const Event& event, const CLuaArguments& Arguments, bool bCallOnChildren) { - return m_pEventManager->Delete(pLuaMain, szName, iLuaFunction); + return s_EventDispatcher.Call(event, Arguments, bCallOnChildren, this); } void CClientEntity::DeleteEvents(CLuaMain* pLuaMain, bool bRecursive) { // Delete it from our events - m_pEventManager->Delete(pLuaMain); + GetEventHandlerCallDispatcher().Remove(pLuaMain); // Delete it from all our children's events if (bRecursive) @@ -836,7 +741,7 @@ void CClientEntity::DeleteEvents(CLuaMain* pLuaMain, bool bRecursive) void CClientEntity::DeleteAllEvents() { - m_pEventManager->DeleteAll(); + GetEventHandlerCallDispatcher().Clear(); } void CClientEntity::CleanUpForVM(CLuaMain* pLuaMain, bool bRecursive) @@ -1310,7 +1215,7 @@ void CClientEntity::SetInterior(unsigned char ucInterior) CLuaArguments Arguments; Arguments.PushNumber(ucOldInterior); Arguments.PushNumber(ucInterior); - CallEvent("onClientElementInteriorChange", Arguments, true); + CallEvent(BuiltInEvents::onClientElementInteriorChange, Arguments, true); } bool CClientEntity::IsOnScreen() diff --git a/Client/mods/deathmatch/logic/CClientEntity.h b/Client/mods/deathmatch/logic/CClientEntity.h index c5453232809..0a8ed72be75 100644 --- a/Client/mods/deathmatch/logic/CClientEntity.h +++ b/Client/mods/deathmatch/logic/CClientEntity.h @@ -16,6 +16,7 @@ class CClientEntity; #include "CClientCommon.h" #include #include "logic/CClientEntityRefManager.h" +#include class CLuaFunctionRef; // Used to check fast version of getElementsByType @@ -87,7 +88,6 @@ class CElementGroup; class CLuaArgument; class CLuaArguments; class CLuaMain; -class CMapEventManager; typedef CFastList CChildListType; // List of elements which is auto deleted when the last user calls Release() @@ -242,12 +242,7 @@ class CClientEntity : public CClientEntityBase virtual bool IsAttachToable(); virtual void DoAttaching(); - bool AddEvent(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction, bool bPropagated, EEventPriorityType eventPriority, - float fPriorityMod); - bool CallEvent(const char* szName, const CLuaArguments& Arguments, bool bCallOnChildren); - void CallEventNoParent(const char* szName, const CLuaArguments& Arguments, CClientEntity* pSource); - void CallParentEvent(const char* szName, const CLuaArguments& Arguments, CClientEntity* pSource); - bool DeleteEvent(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction); + bool CallEvent(const Event& event, const CLuaArguments& Arguments, bool bCallOnChildren = true); void DeleteEvents(CLuaMain* pLuaMain, bool bRecursive); void DeleteAllEvents(); @@ -281,8 +276,6 @@ class CClientEntity : public CClientEntityBase static unsigned int GetTypeID(const char* szTypeName); - CMapEventManager* GetEventManager() { return m_pEventManager; }; - void DeleteClientChildren(); // Returns true if this class is inherited by CClientStreamElement @@ -327,6 +320,57 @@ class CClientEntity : public CClientEntityBase bool CanBeDestroyedByScript() { return m_canBeDestroyedByScript; } void SetCanBeDestroyedByScript(bool canBeDestroyedByScript) { m_canBeDestroyedByScript = canBeDestroyedByScript; } + EventHandlerCallDispatcher& GetEventHandlerCallDispatcher() { return m_eventHandlerCallDispatcher; } + + // Iter a snapshot list of our children + // The snapshot list is inmutable, thus even if it gets modified by + // scripts it wont crash. + // If the provided `Fn` function returns bool `false` + // the given child and its sub-tree will be skipped + // + // TODO: This snapshot list stuff seems absolute bs + // Its inconsistent compared to IterAncestors + // since that function iterates the `live` version + // while this one a `snapshot` + // eg.: Parent gets changed in the middle of iteration: + // it will still iterate the old children, as the snapshot wont be updated + template + void IterChildren(const Fn& fn) + { + auto childrenSnapshot = GetChildrenListSnapshot(); + childrenSnapshot->AddRef(); + for (auto* child : *childrenSnapshot) + { + if (child->IsBeingDeleted()) + continue; + if (IsBeingDeleted()) + break; + // Check if the function returns a bool + if constexpr (std::is_same_v>) + { + if (!fn(child)) + continue; // Skip child and it's sub-tree + } + else + fn(child); + child->IterChildren(fn); // Recurse into child + } + childrenSnapshot->Release(); + } + + template + void IterAncestors(const Fn& fn) + { + for (CClientEntity* it = m_pParent; it; it = it->m_pParent) + fn(it); + } + + template + void IterAncestorsThenChildren(const Fn& fn) + { + IterAncestors(fn); + IterChildren(fn); + } protected: CClientManager* m_pManager; CClientEntity* m_pParent; @@ -336,6 +380,8 @@ class CClientEntity : public CClientEntityBase CCustomData* m_pCustomData; + EventHandlerCallDispatcher m_eventHandlerCallDispatcher; + ElementID m_ID; CVector m_vecRelativePosition; @@ -360,7 +406,6 @@ class CClientEntity : public CClientEntityBase bool m_bBeingDeleted; bool m_bSystemEntity; - CMapEventManager* m_pEventManager; CModelInfo* m_pModelInfo; CFastList m_Collisions; CElementGroup* m_pElementGroup; diff --git a/Client/mods/deathmatch/logic/CClientExplosionManager.cpp b/Client/mods/deathmatch/logic/CClientExplosionManager.cpp index 428d759af7f..fd4e1777283 100644 --- a/Client/mods/deathmatch/logic/CClientExplosionManager.cpp +++ b/Client/mods/deathmatch/logic/CClientExplosionManager.cpp @@ -94,7 +94,7 @@ bool CClientExplosionManager::Hook_ExplosionCreation(CEntity* pGameExplodingEnti Arguments.PushNumber(vecPosition.fY); Arguments.PushNumber(vecPosition.fZ); Arguments.PushNumber(explosionWeaponType); - const bool bAllowExplosion = pResponsible->CallEvent("onClientExplosion", Arguments, true); + const bool bAllowExplosion = pResponsible->CallEvent(BuiltInEvents::onClientExplosion, Arguments, true); return bAllowExplosion; } diff --git a/Client/mods/deathmatch/logic/CClientGUIElement.cpp b/Client/mods/deathmatch/logic/CClientGUIElement.cpp index fdb981da333..ee07940c5fe 100644 --- a/Client/mods/deathmatch/logic/CClientGUIElement.cpp +++ b/Client/mods/deathmatch/logic/CClientGUIElement.cpp @@ -113,33 +113,46 @@ void CClientGUIElement::SetEvents(const char* szFunc1, const char* szFunc2) _strCallbackFunc2 = szFunc2; } +// Hackery for CGUI callback stuff bool CClientGUIElement::_CallbackEvent1(CGUIElement* pCGUIElement) { - CLuaArguments Arg; - if (pCGUIElement) + if (_strCallbackFunc1.empty()) + return false; + + if (const Event* event = Event::Get(_strCallbackFunc1)) { - CClientGUIElement* pElement = m_pGUIManager->Get(pCGUIElement); - if (pElement) + CLuaArguments Arg; + if (pCGUIElement) { - Arg.PushElement(pElement); - pElement->CallEvent(_strCallbackFunc1, Arg, true); - return true; + CClientGUIElement* pElement = m_pGUIManager->Get(pCGUIElement); + if (pElement) + { + Arg.PushElement(pElement); + pElement->CallEvent(*event, Arg, true); + return true; + } } + return false; } - return false; } bool CClientGUIElement::_CallbackEvent2(CGUIElement* pCGUIElement) { - CLuaArguments Arg; - if (pCGUIElement) + if (_strCallbackFunc2.empty()) + return false; + + if (const Event* event = Event::Get(_strCallbackFunc2)) { - CClientGUIElement* pElement = m_pGUIManager->Get(pCGUIElement); - if (pElement) + CLuaArguments Arg; + if (pCGUIElement) { - Arg.PushElement(pElement); - pElement->CallEvent(_strCallbackFunc2, Arg, true); - return true; + CClientGUIElement* pElement = m_pGUIManager->Get(pCGUIElement); + if (pElement) + { + Arg.PushElement(pElement); + pElement->CallEvent(*event, Arg, true); + return true; + } } } return false; diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index e5250402cd5..9e594b3b7dd 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -16,6 +16,7 @@ #include "game/CAnimBlendHierarchy.h" #include #include "CServerInfo.h" +#include SString StringZeroPadout(const SString& strInput, uint uiPadoutSize) { @@ -287,7 +288,7 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo()) m_pScriptDebugging = new CScriptDebugging(m_pLuaManager); m_pScriptDebugging->SetLogfile(CalcMTASAPath("mta\\logs\\clientscript.log"), 3); - CStaticFunctionDefinitions(m_pLuaManager, &m_Events, g_pCore, g_pGame, this, m_pManager); + CStaticFunctionDefinitions(m_pLuaManager, g_pCore, g_pGame, this, m_pManager); CLuaFunctionDefs::Initialize(m_pLuaManager, m_pScriptDebugging, this); CLuaDefs::Initialize(this, m_pLuaManager, m_pScriptDebugging); @@ -322,9 +323,6 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo()) m_bShowInterpolation = false; #endif - // Add our lua events - AddBuiltInEvents(); - // Init debugger class m_Foo.Init(this); @@ -460,6 +458,9 @@ CClientGame::~CClientGame() g_pCore->ForceCursorVisible(false); SetCursorEventsEnabled(false); + // Probably not neccessary as (im not sure) dll i unloaded on (re)connect + s_CustomEvents.Clear(); + // Destroy our stuff SAFE_DELETE(m_pManager); // Will trigger onClientResourceStop SAFE_DELETE(m_pNametags); @@ -739,7 +740,7 @@ void CClientGame::DoPulsePreHUDRender(bool bDidUnminimize, bool bDidRecreateRend { CLuaArguments Arguments; Arguments.PushBoolean(bDidRecreateRenderTargets); - m_pRootEntity->CallEvent("onClientRestore", Arguments, false); + m_pRootEntity->CallEvent(BuiltInEvents::onClientRestore, Arguments, false); m_bWasMinimized = false; // Reverse any mute on minimize effects @@ -750,7 +751,7 @@ void CClientGame::DoPulsePreHUDRender(bool bDidUnminimize, bool bDidRecreateRend // Call onClientHUDRender LUA event CLuaArguments Arguments; - m_pRootEntity->CallEvent("onClientHUDRender", Arguments, false); + m_pRootEntity->CallEvent(BuiltInEvents::onClientHUDRender, Arguments, false); // Disallow scripted dxSetRenderTarget for old scripts g_pCore->GetGraphics()->GetRenderItemManager()->EnableSetRenderTargetOldVer(false); @@ -1132,7 +1133,7 @@ void CClientGame::DoPulses() // Call onClientRender LUA event CLuaArguments Arguments; - m_pRootEntity->CallEvent("onClientRender", Arguments, false); + m_pRootEntity->CallEvent(BuiltInEvents::onClientRender, Arguments, false); // Disallow scripted dxSetRenderTarget for old scripts g_pCore->GetGraphics()->GetRenderItemManager()->EnableSetRenderTargetOldVer(false); @@ -1613,7 +1614,7 @@ void CClientGame::UpdatePlayerTarget() Arguments.PushElement(m_pTargetedEntity); else Arguments.PushBoolean(false); - m_pLocalPlayer->CallEvent("onClientPlayerTarget", Arguments, true); + m_pLocalPlayer->CallEvent(BuiltInEvents::onClientPlayerTarget, Arguments, true); } } @@ -1626,7 +1627,7 @@ void CClientGame::UpdatePlayerWeapons() CLuaArguments Arguments; Arguments.PushNumber(m_lastWeaponSlot); Arguments.PushNumber(currentSlot); - bool bCancelled = !m_pLocalPlayer->CallEvent("onClientPlayerWeaponSwitch", Arguments, true); + bool bCancelled = !m_pLocalPlayer->CallEvent(BuiltInEvents::onClientPlayerWeaponSwitch, Arguments, true); if (bCancelled) { @@ -1827,7 +1828,7 @@ void CClientGame::UpdateFireKey() pControl->bState = false; CLuaArguments Arguments; Arguments.PushElement(pTargetPed); - if (m_pLocalPlayer->CallEvent("onClientPlayerStealthKill", Arguments, false)) + if (m_pLocalPlayer->CallEvent(BuiltInEvents::onClientPlayerStealthKill, Arguments, false)) { if (pTargetPed->IsLocalEntity()) { @@ -1865,7 +1866,7 @@ void CClientGame::UpdateStunts() // Call our stunt event CLuaArguments Arguments; Arguments.PushString("2wheeler"); - m_pLocalPlayer->CallEvent("onClientPlayerStuntStart", Arguments, true); + m_pLocalPlayer->CallEvent(BuiltInEvents::onClientPlayerStuntStart, Arguments, true); } // Did we finish a stunt? else if (ulLastCarTwoWheelCounter != 0 && ulTemp == 0) @@ -1877,7 +1878,7 @@ void CClientGame::UpdateStunts() Arguments.PushString("2wheeler"); Arguments.PushNumber(ulLastCarTwoWheelCounter); Arguments.PushNumber(fDistance); - m_pLocalPlayer->CallEvent("onClientPlayerStuntFinish", Arguments, true); + m_pLocalPlayer->CallEvent(BuiltInEvents::onClientPlayerStuntFinish, Arguments, true); } ulLastCarTwoWheelCounter = ulTemp; fLastCarTwoWheelDist = g_pGame->GetPlayerInfo()->GetCarTwoWheelDist(); @@ -1892,7 +1893,7 @@ void CClientGame::UpdateStunts() // Call our stunt event CLuaArguments Arguments; Arguments.PushString("wheelie"); - m_pLocalPlayer->CallEvent("onClientPlayerStuntStart", Arguments, true); + m_pLocalPlayer->CallEvent(BuiltInEvents::onClientPlayerStuntStart, Arguments, true); } // Did we finish a stunt? else if (ulLastBikeRearWheelCounter != 0 && ulTemp == 0) @@ -1904,7 +1905,7 @@ void CClientGame::UpdateStunts() Arguments.PushString("wheelie"); Arguments.PushNumber(ulLastBikeRearWheelCounter); Arguments.PushNumber(fDistance); - m_pLocalPlayer->CallEvent("onClientPlayerStuntFinish", Arguments, true); + m_pLocalPlayer->CallEvent(BuiltInEvents::onClientPlayerStuntFinish, Arguments, true); } ulLastBikeRearWheelCounter = ulTemp; fLastBikeRearWheelDist = g_pGame->GetPlayerInfo()->GetBikeRearWheelDist(); @@ -1919,7 +1920,7 @@ void CClientGame::UpdateStunts() // Call our stunt event CLuaArguments Arguments; Arguments.PushString("stoppie"); - m_pLocalPlayer->CallEvent("onClientPlayerStuntStart", Arguments, true); + m_pLocalPlayer->CallEvent(BuiltInEvents::onClientPlayerStuntStart, Arguments, true); } // Did we finish a stunt? else if (ulLastBikeFrontWheelCounter != 0 && ulTemp == 0) @@ -1931,7 +1932,7 @@ void CClientGame::UpdateStunts() Arguments.PushString("stoppie"); Arguments.PushNumber(ulLastBikeFrontWheelCounter); Arguments.PushNumber(fDistance); - m_pLocalPlayer->CallEvent("onClientPlayerStuntFinish", Arguments, true); + m_pLocalPlayer->CallEvent(BuiltInEvents::onClientPlayerStuntFinish, Arguments, true); } ulLastBikeFrontWheelCounter = ulTemp; fLastBikeFrontWheelDist = g_pGame->GetPlayerInfo()->GetBikeFrontWheelDist(); @@ -2051,7 +2052,7 @@ bool CClientGame::KeyStrokeHandler(const SString& strKey, bool bState, bool bIsC CLuaArguments Arguments; Arguments.PushString(strKey); Arguments.PushBoolean(bState); - bAllow = m_pRootEntity->CallEvent("onClientKey", Arguments, false); + bAllow = m_pRootEntity->CallEvent(BuiltInEvents::onClientKey, Arguments, false); if (bState == true) { if (bAllow == false && strKey == "escape") @@ -2102,7 +2103,7 @@ bool CClientGame::CharacterKeyHandler(WPARAM wChar) // Call our character event CLuaArguments Arguments; Arguments.PushString(strANSI); - m_pRootEntity->CallEvent("onClientCharacter", Arguments, false); + m_pRootEntity->CallEvent(BuiltInEvents::onClientCharacter, Arguments, false); } } @@ -2306,7 +2307,7 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa Arguments.PushElement(pCollisionEntity); else Arguments.PushBoolean(false); - m_pRootEntity->CallEvent("onClientClick", Arguments, false); + m_pRootEntity->CallEvent(BuiltInEvents::onClientClick, Arguments, false); // Send the button, cursor position, 3d position and the entity collided with CBitStream bitStream; @@ -2350,7 +2351,7 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa DoubleClickArguments.PushElement(pCollisionEntity); else DoubleClickArguments.PushBoolean(false); - m_pRootEntity->CallEvent("onClientDoubleClick", DoubleClickArguments, false); + m_pRootEntity->CallEvent(BuiltInEvents::onClientDoubleClick, DoubleClickArguments, false); } m_ulLastClickTick = GetTickCount32(); @@ -2388,7 +2389,7 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa Arguments.PushNumber((double)vecTarget.fX); Arguments.PushNumber((double)vecTarget.fY); Arguments.PushNumber((double)vecTarget.fZ); - m_pRootEntity->CallEvent("onClientCursorMove", Arguments, false); + m_pRootEntity->CallEvent(BuiltInEvents::onClientCursorMove, Arguments, false); } break; } @@ -2452,181 +2453,6 @@ void CClientGame::SetWanted(DWORD dwWanted) m_dwWanted = dwWanted; } -void CClientGame::AddBuiltInEvents() -{ - // Resource events - m_Events.AddEvent("onClientResourceStart", "resource", NULL, false); - m_Events.AddEvent("onClientResourceStop", "resource", NULL, false); - - // Element events - m_Events.AddEvent("onClientElementDataChange", "name", NULL, false); - m_Events.AddEvent("onClientElementStreamIn", "", NULL, false); - m_Events.AddEvent("onClientElementStreamOut", "", NULL, false); - m_Events.AddEvent("onClientElementDestroy", "", NULL, false); - m_Events.AddEvent("onClientElementModelChange", "oldModel, newModel", nullptr, false); - m_Events.AddEvent("onClientElementDimensionChange", "oldDimension, newDimension", nullptr, false); - m_Events.AddEvent("onClientElementInteriorChange", "oldInterior, newInterior", nullptr, false); - - // Player events - m_Events.AddEvent("onClientPlayerJoin", "", NULL, false); - m_Events.AddEvent("onClientPlayerQuit", "reason", NULL, false); - m_Events.AddEvent("onClientPlayerTarget", "target", NULL, false); - m_Events.AddEvent("onClientPlayerSpawn", "team", NULL, false); - m_Events.AddEvent("onClientPlayerChangeNick", "oldNick", NULL, false); - m_Events.AddEvent("onClientPlayerVehicleEnter", "vehicle, seat", NULL, false); - m_Events.AddEvent("onClientPlayerVehicleExit", "vehicle, seat", NULL, false); - m_Events.AddEvent("onClientPlayerTask", "priority, slot, name", NULL, false); - m_Events.AddEvent("onClientPlayerWeaponSwitch", "previous, current", NULL, false); - m_Events.AddEvent("onClientPlayerStuntStart", "type", NULL, false); - m_Events.AddEvent("onClientPlayerStuntFinish", "type, time, distance", NULL, false); - m_Events.AddEvent("onClientPlayerRadioSwitch", "", NULL, false); - m_Events.AddEvent("onClientPlayerDamage", "attacker, weapon, bodypart", NULL, false); - m_Events.AddEvent("onClientPlayerWeaponFire", "weapon, ammo, ammoInClip, hitX, hitY, hitZ, hitElement", NULL, false); - m_Events.AddEvent("onClientPlayerWasted", "", NULL, false); - m_Events.AddEvent("onClientPlayerChoke", "", NULL, false); - m_Events.AddEvent("onClientPlayerVoiceStart", "", NULL, false); - m_Events.AddEvent("onClientPlayerVoiceStop", "", NULL, false); - m_Events.AddEvent("onClientPlayerVoicePause", "reason", NULL, false); - m_Events.AddEvent("onClientPlayerVoiceResumed", "reason", NULL, false); - m_Events.AddEvent("onClientPlayerStealthKill", "target", NULL, false); - m_Events.AddEvent("onClientPlayerHitByWaterCannon", "vehicle", NULL, false); - m_Events.AddEvent("onClientPlayerHeliKilled", "heli", NULL, false); - m_Events.AddEvent("onClientPlayerPickupHit", "pickup, matchingDimension", NULL, false); - m_Events.AddEvent("onClientPlayerPickupLeave", "pickup, matchingDimension", NULL, false); - m_Events.AddEvent("onClientPlayerNetworkStatus", "type, ticks", NULL, false); - - // Ped events - m_Events.AddEvent("onClientPedDamage", "attacker, weapon, bodypart", NULL, false); - m_Events.AddEvent("onClientPedVehicleEnter", "vehicle, seat", NULL, false); - m_Events.AddEvent("onClientPedVehicleExit", "vehicle, seat", NULL, false); - m_Events.AddEvent("onClientPedWeaponFire", "weapon, ammo, ammoInClip, hitX, hitY, hitZ, hitElement", NULL, false); - m_Events.AddEvent("onClientPedWasted", "", NULL, false); - m_Events.AddEvent("onClientPedChoke", "", NULL, false); - m_Events.AddEvent("onClientPedHeliKilled", "heli", NULL, false); - m_Events.AddEvent("onClientPedHitByWaterCannon", "vehicle", NULL, false); - m_Events.AddEvent("onClientPedStep", "foot", nullptr, false); - - // Vehicle events - m_Events.AddEvent("onClientVehicleRespawn", "", NULL, false); - m_Events.AddEvent("onClientVehicleEnter", "player, seat", NULL, false); - m_Events.AddEvent("onClientVehicleExit", "player, seat", NULL, false); - m_Events.AddEvent("onClientVehicleStartEnter", "player, seat", NULL, false); - m_Events.AddEvent("onClientVehicleStartExit", "player, seat", NULL, false); - m_Events.AddEvent("onClientTrailerAttach", "towedBy", NULL, false); - m_Events.AddEvent("onClientTrailerDetach", "towedBy", NULL, false); - m_Events.AddEvent("onClientVehicleExplode", "", NULL, false); - m_Events.AddEvent("onClientVehicleCollision", "collidedelement, damageImpulseMag, bodypart, x, y, z, velX, velY, velZ", NULL, false); - m_Events.AddEvent("onClientVehicleDamage", "attacker, weapon, loss, x, y, z, tyre", NULL, false); - m_Events.AddEvent("onClientVehicleNitroStateChange", "activated", NULL, false); - m_Events.AddEvent("onClientVehicleWeaponHit", "weaponType, hitElement, hitX, hitY, hitZ, model, materialID", nullptr, false); - - // GUI events - m_Events.AddEvent("onClientGUIClick", "button, state, absoluteX, absoluteY", NULL, false); - m_Events.AddEvent("onClientGUIDoubleClick", "button, state, absoluteX, absoluteY", NULL, false); - m_Events.AddEvent("onClientGUIMouseDown", "button, absoluteX, absoluteY", NULL, false); - m_Events.AddEvent("onClientGUIMouseUp", "button, absoluteX, absoluteY", NULL, false); - m_Events.AddEvent("onClientGUIScroll", "element", NULL, false); - m_Events.AddEvent("onClientGUIChanged", "element", NULL, false); - m_Events.AddEvent("onClientGUIAccepted", "element", NULL, false); - // m_Events.AddEvent ( "onClientGUIClose", "element", NULL, false ); - // m_Events.AddEvent ( "onClientGUIKeyDown", "element", NULL, false ); - m_Events.AddEvent("onClientGUITabSwitched", "element", NULL, false); - m_Events.AddEvent("onClientGUIComboBoxAccepted", "element", NULL, false); - - // Input events - m_Events.AddEvent("onClientDoubleClick", "button, screenX, screenY, worldX, worldY, worldZ, element", NULL, false); - m_Events.AddEvent("onClientMouseMove", "screenX, screenY", NULL, false); - m_Events.AddEvent("onClientMouseEnter", "screenX, screenY", NULL, false); - m_Events.AddEvent("onClientMouseLeave", "screenX, screenY", NULL, false); - m_Events.AddEvent("onClientMouseWheel", "", NULL, false); - m_Events.AddEvent("onClientGUIMove", "", NULL, false); - m_Events.AddEvent("onClientGUISize", "", NULL, false); - m_Events.AddEvent("onClientGUIFocus", "", NULL, false); - m_Events.AddEvent("onClientGUIBlur", "", NULL, false); - m_Events.AddEvent("onClientKey", "key, state", NULL, false); - m_Events.AddEvent("onClientCharacter", "character", NULL, false); - m_Events.AddEvent("onClientPaste", "clipboardText", NULL, false); - - // Console events - m_Events.AddEvent("onClientConsole", "text", NULL, false); - - // Chat events - m_Events.AddEvent("onClientChatMessage", "test, r, g, b", NULL, false); - - // Debug events - m_Events.AddEvent("onClientDebugMessage", "message, level, file, line", NULL, false); - - // Game events - m_Events.AddEvent("onClientPreRender", "", NULL, false); - m_Events.AddEvent("onClientPedsProcessed", "", NULL, false); - m_Events.AddEvent("onClientHUDRender", "", NULL, false); - m_Events.AddEvent("onClientRender", "", NULL, false); - m_Events.AddEvent("onClientMinimize", "", NULL, false); - m_Events.AddEvent("onClientRestore", "", NULL, false); - - // Cursor events - m_Events.AddEvent("onClientClick", "button, state, screenX, screenY, worldX, worldY, worldZ, gui_clicked", NULL, false); - m_Events.AddEvent("onClientCursorMove", "relativeX, relativeX, absoluteX, absoluteY, worldX, worldY, worldZ", NULL, false); - - // Marker events - m_Events.AddEvent("onClientMarkerHit", "entity, matchingDimension", NULL, false); - m_Events.AddEvent("onClientMarkerLeave", "entity, matchingDimension", NULL, false); - - // Marker events - m_Events.AddEvent("onClientPickupHit", "entity, matchingDimension", NULL, false); - m_Events.AddEvent("onClientPickupLeave", "entity, matchingDimension", NULL, false); - - // Col-shape events - m_Events.AddEvent("onClientColShapeHit", "entity, matchingDimension", NULL, false); - m_Events.AddEvent("onClientColShapeLeave", "entity, matchingDimension", NULL, false); - m_Events.AddEvent("onClientElementColShapeHit", "colShape, matchingDimension", NULL, false); - m_Events.AddEvent("onClientElementColShapeLeave", "colShape, matchingDimension", NULL, false); - - // Explosion events - m_Events.AddEvent("onClientExplosion", "x, y, z, type", NULL, false); - - // Projectile events - m_Events.AddEvent("onClientProjectileCreation", "creator", NULL, false); - - // Sound events - m_Events.AddEvent("onClientSoundStream", "success, length, streamName, error", NULL, false); - m_Events.AddEvent("onClientSoundFinishedDownload", "length", NULL, false); - m_Events.AddEvent("onClientSoundChangedMeta", "streamTitle", NULL, false); - m_Events.AddEvent("onClientSoundStarted", "reason", NULL, false); - m_Events.AddEvent("onClientSoundStopped", "reason", NULL, false); - m_Events.AddEvent("onClientSoundBeat", "time", NULL, false); - - // Object events - m_Events.AddEvent("onClientObjectDamage", "loss, attacker", NULL, false); - m_Events.AddEvent("onClientObjectBreak", "attacker", NULL, false); - m_Events.AddEvent("onClientObjectMoveStart", "", NULL, false); - m_Events.AddEvent("onClientObjectMoveStop", "", NULL, false); - - // Web events - m_Events.AddEvent("onClientBrowserWhitelistChange", "newPages", NULL, false); - m_Events.AddEvent("onClientBrowserCreated", "", NULL, false); - m_Events.AddEvent("onClientBrowserLoadingStart", "url, mainframe", NULL, false); - m_Events.AddEvent("onClientBrowserDocumentReady", "url", NULL, false); - m_Events.AddEvent("onClientBrowserLoadingFailed", "url, errorcode, errordescription", NULL, false); - m_Events.AddEvent("onClientBrowserNavigate", "url, isblocked", NULL, false); - m_Events.AddEvent("onClientBrowserPopup", "targeturl, openerurl, ispopup", NULL, false); - m_Events.AddEvent("onClientBrowserCursorChange", "cursor", NULL, false); - m_Events.AddEvent("onClientBrowserTooltip", "text", NULL, false); - m_Events.AddEvent("onClientBrowserInputFocusChanged", "gainedfocus", NULL, false); - m_Events.AddEvent("onClientBrowserResourceBlocked", "url, domain, reason", NULL, false); - - // Misc events - m_Events.AddEvent("onClientFileDownloadComplete", "fileName, success", NULL, false); - - m_Events.AddEvent("onClientResourceFileDownload", "resource, fileName, fileSize, state", nullptr, false); - m_Events.AddEvent("onClientTransferBoxProgressChange", "downloadedBytes, downloadTotalBytes", nullptr, false); - m_Events.AddEvent("onClientTransferBoxVisibilityChange", "isVisible", nullptr, false); - - m_Events.AddEvent("onClientWeaponFire", "ped, x, y, z", NULL, false); - - m_Events.AddEvent("onClientWorldSound", "group, index, x, y, z", nullptr, false); -} - void CClientGame::DrawFPS() { // Draw the background @@ -3222,7 +3048,7 @@ void CClientGame::QuitPlayer(CClientPlayer* pPlayer, eQuitReason Reason) // Call our onClientPlayerQuit event CLuaArguments Arguments; Arguments.PushString(szReason); - pPlayer->CallEvent("onClientPlayerQuit", Arguments, true); + pPlayer->CallEvent(BuiltInEvents::onClientPlayerQuit, Arguments, true); // Detach the camera from this player if we're watching them m_pManager->GetCamera()->UnreferencePlayer(pPlayer); @@ -3347,7 +3173,7 @@ void CClientGame::SetupGlobalLuaEvents() // Call event now CLuaArguments args; args.PushString(clipboardText); - m_pRootEntity->CallEvent("onClientPaste", args, false); + m_pRootEntity->CallEvent(BuiltInEvents::onClientPaste, args, false); }); } @@ -3652,7 +3478,7 @@ void CClientGame::ProjectileInitiateHandler(CClientProjectile* pProjectile) // Call our creation event CLuaArguments Arguments; Arguments.PushElement(pProjectile->GetCreator()); - pProjectile->CallEvent("onClientProjectileCreation", Arguments, true); + pProjectile->CallEvent(BuiltInEvents::onClientProjectileCreation, Arguments, true); } void CClientGame::Render3DStuffHandler() @@ -3681,13 +3507,13 @@ void CClientGame::PostWorldProcessHandler() // Call onClientPreRender LUA event CLuaArguments Arguments; Arguments.PushNumber(dTimeSlice); - m_pRootEntity->CallEvent("onClientPreRender", Arguments, false); + m_pRootEntity->CallEvent(BuiltInEvents::onClientPreRender, Arguments, false); } void CClientGame::PostWorldProcessPedsAfterPreRenderHandler() { CLuaArguments Arguments; - m_pRootEntity->CallEvent("onClientPedsProcessed", Arguments, false); + m_pRootEntity->CallEvent(BuiltInEvents::onClientPedsProcessed, Arguments, false); } void CClientGame::IdleHandler() @@ -3700,7 +3526,7 @@ void CClientGame::IdleHandler() m_bWasMinimized = true; // Call onClientMinimize LUA event CLuaArguments Arguments; - m_pRootEntity->CallEvent("onClientMinimize", Arguments, false); + m_pRootEntity->CallEvent(BuiltInEvents::onClientMinimize, Arguments, false); bool bMuteAll = g_pCore->GetCVars()->GetValue("mute_master_when_minimized"); @@ -3731,7 +3557,7 @@ bool CClientGame::ChokingHandler(unsigned char ucWeaponType) return true; CLuaArguments Arguments; Arguments.PushNumber(ucWeaponType); - return m_pLocalPlayer->CallEvent("onClientPlayerChoke", Arguments, true); + return m_pLocalPlayer->CallEvent(BuiltInEvents::onClientPlayerChoke, Arguments, true); } void CClientGame::CAnimBlendAssocDestructorHandler(CAnimBlendAssociationSAInterface* pThis) @@ -4203,8 +4029,8 @@ bool CClientGame::ApplyPedDamageFromGame(eWeaponType weaponUsed, float fDamage, Arguments.PushNumber(fDamage); // Call our event - if ((IS_PLAYER(pDamagedPed) && !pDamagedPed->CallEvent("onClientPlayerDamage", Arguments, true)) || - (!IS_PLAYER(pDamagedPed) && !pDamagedPed->CallEvent("onClientPedDamage", Arguments, true))) + if ((IS_PLAYER(pDamagedPed) && !pDamagedPed->CallEvent(BuiltInEvents::onClientPlayerDamage, Arguments, true)) || + (!IS_PLAYER(pDamagedPed) && !pDamagedPed->CallEvent(BuiltInEvents::onClientPedDamage, Arguments, true))) { // Stop here if they cancelEvent it if (pDamagedPed->IsLocalPlayer()) @@ -4306,7 +4132,7 @@ bool CClientGame::ApplyPedDamageFromGame(eWeaponType weaponUsed, float fDamage, if (pDamagedPed->IsLocalEntity() && fPreviousHealth > 0.0f) { // Client-side ped - pDamagedPed->CallEvent("onClientPedWasted", Arguments, true); + pDamagedPed->CallEvent(BuiltInEvents::onClientPedWasted, Arguments, true); AssocGroupId animGroup; AnimationId animID; GetDeathAnim(pDamagedPed, pEvent, animGroup, animID); @@ -4372,7 +4198,7 @@ void CClientGame::DeathHandler(CPed* pKilledPedSA, unsigned char ucDeathReason, Arguments.PushNumber(ucDeathReason); Arguments.PushNumber(ucBodyPart); - pKilledPed->CallEvent("onClientPedWasted", Arguments, true); + pKilledPed->CallEvent(BuiltInEvents::onClientPedWasted, Arguments, true); // Notify the server SendPedWastedPacket(pKilledPed, INVALID_ELEMENT_ID, ucDeathReason, ucBodyPart); @@ -4416,7 +4242,7 @@ bool CClientGame::VehicleCollisionHandler(CVehicleSAInterface*& pCollidingVehicl Arguments.PushNumber(fCollidingDamageImpulseMag); Arguments.PushNumber(iModelIndex); - pVehicleClientEntity->CallEvent("onClientVehicleCollision", Arguments, true); + pVehicleClientEntity->CallEvent(BuiltInEvents::onClientVehicleCollision, Arguments, true); // Update the colliding vehicle, because it might have been invalidated in onClientVehicleCollision (e.g. fixVehicle) pCollidingVehicle = reinterpret_cast(pVehicleClientEntity->GetGameEntity()->GetInterface()); @@ -4517,9 +4343,9 @@ bool CClientGame::HeliKillHandler(CVehicleSAInterface* pHeliInterface, CEntitySA // Trigger our event bool bContinue; if (IS_PLAYER(pClientPed)) - bContinue = pClientPed->CallEvent("onClientPlayerHeliKilled", Arguments, true); + bContinue = pClientPed->CallEvent(BuiltInEvents::onClientPlayerHeliKilled, Arguments, true); else - bContinue = pClientPed->CallEvent("onClientPedHeliKilled", Arguments, true); + bContinue = pClientPed->CallEvent(BuiltInEvents::onClientPedHeliKilled, Arguments, true); // Was our event cancelled if (!bContinue) @@ -4576,7 +4402,7 @@ bool CClientGame::VehicleDamageHandler(CEntitySAInterface* pVehicleInterface, fl else Arguments.PushNil(); - if (!pClientVehicle->CallEvent("onClientVehicleDamage", Arguments, true)) + if (!pClientVehicle->CallEvent(BuiltInEvents::onClientVehicleDamage, Arguments, true)) { bAllowDamage = false; } @@ -4607,7 +4433,7 @@ bool CClientGame::ObjectDamageHandler(CObjectSAInterface* pObjectInterface, floa else Arguments.PushNil(); - return pClientObject->CallEvent("onClientObjectDamage", Arguments, true); + return pClientObject->CallEvent(BuiltInEvents::onClientObjectDamage, Arguments, true); } } return true; @@ -4641,7 +4467,7 @@ bool CClientGame::ObjectBreakHandler(CObjectSAInterface* pObjectInterface, CEnti else Arguments.PushNil(); - return pClientObject->CallEvent("onClientObjectBreak", Arguments, true); + return pClientObject->CallEvent(BuiltInEvents::onClientObjectBreak, Arguments, true); } } return true; @@ -4681,9 +4507,9 @@ bool CClientGame::WaterCannonHitHandler(CVehicleSAInterface* pCannonVehicle, CPe // Trigger our event bool bContinue = true; if (pClientPed && !IS_PLAYER(pClientPed)) - bContinue = pCannonClientVehicle->CallEvent("onClientPedHitByWaterCannon", Arguments, true); + bContinue = pCannonClientVehicle->CallEvent(BuiltInEvents::onClientPedHitByWaterCannon, Arguments, true); else - bContinue = pCannonClientVehicle->CallEvent("onClientPlayerHitByWaterCannon", Arguments, true); + bContinue = pCannonClientVehicle->CallEvent(BuiltInEvents::onClientPlayerHitByWaterCannon, Arguments, true); // Return if it was cancelled return bContinue; @@ -4969,10 +4795,10 @@ void CClientGame::PostWeaponFire() Arguments.PushNumber((double)vecOrigin.fX); Arguments.PushNumber((double)vecOrigin.fY); Arguments.PushNumber((double)vecOrigin.fZ); - pPed->CallEvent("onClientPlayerWeaponFire", Arguments, true); + pPed->CallEvent(BuiltInEvents::onClientPlayerWeaponFire, Arguments, true); } else - pPed->CallEvent("onClientPedWeaponFire", Arguments, true); + pPed->CallEvent(BuiltInEvents::onClientPedWeaponFire, Arguments, true); } pPed->PostWeaponFire(); #ifdef MTA_DEBUG @@ -5452,7 +5278,7 @@ void CClientGame::DoWastedCheck(ElementID damagerID, unsigned char ucWeapon, uns else Arguments.PushBoolean(false); Arguments.PushBoolean(false); - m_pLocalPlayer->CallEvent("onClientPlayerWasted", Arguments, true); + m_pLocalPlayer->CallEvent(BuiltInEvents::onClientPlayerWasted, Arguments, true); // Write some death info pBitStream->WriteCompressed(animGroup); @@ -5527,7 +5353,7 @@ bool CClientGame::OnMouseClick(CGUIMouseEventArgs Args) CClientGUIElement* pGUIElement = CGUI_GET_CCLIENTGUIELEMENT(Args.pWindow); if (GetGUIManager()->Exists(pGUIElement)) { - pGUIElement->CallEvent("onClientGUIClick", Arguments, true); + pGUIElement->CallEvent(BuiltInEvents::onClientGUIClick, Arguments, true); } } @@ -5568,7 +5394,7 @@ bool CClientGame::OnMouseDoubleClick(CGUIMouseEventArgs Args) CClientGUIElement* pGUIElement = CGUI_GET_CCLIENTGUIELEMENT(Args.pWindow); if (GetGUIManager()->Exists(pGUIElement)) { - pGUIElement->CallEvent("onClientGUIDoubleClick", Arguments, true); + pGUIElement->CallEvent(BuiltInEvents::onClientGUIDoubleClick, Arguments, true); } } @@ -5604,7 +5430,7 @@ bool CClientGame::OnMouseButtonDown(CGUIMouseEventArgs Args) CClientGUIElement* pGUIElement = CGUI_GET_CCLIENTGUIELEMENT(Args.pWindow); if (GetGUIManager()->Exists(pGUIElement)) { - pGUIElement->CallEvent("onClientGUIMouseDown", Arguments, true); + pGUIElement->CallEvent(BuiltInEvents::onClientGUIMouseDown, Arguments, true); } } @@ -5640,7 +5466,7 @@ bool CClientGame::OnMouseButtonUp(CGUIMouseEventArgs Args) CClientGUIElement* pGUIElement = CGUI_GET_CCLIENTGUIELEMENT(Args.pWindow); if (GetGUIManager()->Exists(pGUIElement)) { - pGUIElement->CallEvent("onClientGUIMouseUp", Arguments, true); + pGUIElement->CallEvent(BuiltInEvents::onClientGUIMouseUp, Arguments, true); } } @@ -5658,7 +5484,7 @@ bool CClientGame::OnMouseMove(CGUIMouseEventArgs Args) CClientGUIElement* pGUIElement = CGUI_GET_CCLIENTGUIELEMENT(Args.pWindow); if (GetGUIManager()->Exists(pGUIElement)) - pGUIElement->CallEvent("onClientMouseMove", Arguments, true); + pGUIElement->CallEvent(BuiltInEvents::onClientMouseMove, Arguments, true); return true; } @@ -5680,7 +5506,7 @@ bool CClientGame::OnMouseEnter(CGUIMouseEventArgs Args) CClientGUIElement* pGUIElement = CGUI_GET_CCLIENTGUIELEMENT(Args.pWindow); if (GetGUIManager()->Exists(pGUIElement)) - pGUIElement->CallEvent("onClientMouseEnter", Arguments, true); + pGUIElement->CallEvent(BuiltInEvents::onClientMouseEnter, Arguments, true); return true; } @@ -5702,7 +5528,7 @@ bool CClientGame::OnMouseLeave(CGUIMouseEventArgs Args) CClientGUIElement* pGUIElement = CGUI_GET_CCLIENTGUIELEMENT(Args.pWindow); if (GetGUIManager()->Exists(pGUIElement)) - pGUIElement->CallEvent("onClientMouseLeave", Arguments, true); + pGUIElement->CallEvent(BuiltInEvents::onClientMouseLeave, Arguments, true); return true; } @@ -5717,7 +5543,7 @@ bool CClientGame::OnMouseWheel(CGUIMouseEventArgs Args) CClientGUIElement* pGUIElement = CGUI_GET_CCLIENTGUIELEMENT(Args.pWindow); if (GetGUIManager()->Exists(pGUIElement)) - pGUIElement->CallEvent("onClientMouseWheel", Arguments, true); + pGUIElement->CallEvent(BuiltInEvents::onClientMouseWheel, Arguments, true); return true; } @@ -5731,7 +5557,7 @@ bool CClientGame::OnMove(CGUIElement* pElement) CClientGUIElement* pGUIElement = CGUI_GET_CCLIENTGUIELEMENT(pElement); if (pGUIElement && GetGUIManager()->Exists(pGUIElement)) - pGUIElement->CallEvent("onClientGUIMove", Arguments, true); + pGUIElement->CallEvent(BuiltInEvents::onClientGUIMove, Arguments, true); return true; } @@ -5745,7 +5571,7 @@ bool CClientGame::OnSize(CGUIElement* pElement) CClientGUIElement* pGUIElement = CGUI_GET_CCLIENTGUIELEMENT(pElement); if (GetGUIManager()->Exists(pGUIElement)) - pGUIElement->CallEvent("onClientGUISize", Arguments, true); + pGUIElement->CallEvent(BuiltInEvents::onClientGUISize, Arguments, true); return true; } @@ -5763,11 +5589,11 @@ bool CClientGame::OnFocusGain(CGUIFocusEventArgs Args) { CClientGUIElement* pDeactivatedGUIElement = CGUI_GET_CCLIENTGUIELEMENT(Args.pDeactivatedWindow); if (GetGUIManager()->Exists(pDeactivatedGUIElement)) - pDeactivatedGUIElement->CallEvent("onClientGUIBlur", Arguments, true); + pDeactivatedGUIElement->CallEvent(BuiltInEvents::onClientGUIBlur, Arguments, true); } if (GetGUIManager()->Exists(pActivatedGUIElement)) - pActivatedGUIElement->CallEvent("onClientGUIFocus", Arguments, true); + pActivatedGUIElement->CallEvent(BuiltInEvents::onClientGUIFocus, Arguments, true); return true; } @@ -5787,7 +5613,7 @@ bool CClientGame::OnFocusLoss(CGUIFocusEventArgs Args) CClientGUIElement* pDeactivatedGUIElement = CGUI_GET_CCLIENTGUIELEMENT(Args.pDeactivatedWindow); if (GetGUIManager()->Exists(pDeactivatedGUIElement)) - pDeactivatedGUIElement->CallEvent("onClientGUIBlur", Arguments, true); + pDeactivatedGUIElement->CallEvent(BuiltInEvents::onClientGUIBlur, Arguments, true); return true; } @@ -6195,7 +6021,7 @@ bool CClientGame::WorldSoundHandler(const SWorldSoundEvent& event) Arguments.PushNumber(event.vecPosition.fX); Arguments.PushNumber(event.vecPosition.fY); Arguments.PushNumber(event.vecPosition.fZ); - return pEntity->CallEvent("onClientWorldSound", Arguments, true); + return pEntity->CallEvent(BuiltInEvents::onClientWorldSound, Arguments, true); } } @@ -6454,7 +6280,7 @@ bool CClientGame::TriggerBrowserRequestResultEvent(const std::unordered_setCallEvent("onClientBrowserWhitelistChange", Arguments, false); + return GetRootEntity()->CallEvent(BuiltInEvents::onClientBrowserWhitelistChange, Arguments, false); } void CClientGame::RestreamModel(unsigned short usModel) @@ -6628,7 +6454,7 @@ void CClientGame::PedStepHandler(CPedSAInterface* pPedSA, bool bFoot) if (pClientPed) { Arguments.PushBoolean(bFoot); - pClientPed->CallEvent("onClientPedStep", Arguments, true); + pClientPed->CallEvent(BuiltInEvents::onClientPedStep, Arguments, true); } } @@ -6662,7 +6488,7 @@ void CClientGame::VehicleWeaponHitHandler(SVehicleWeaponHitEvent& event) arguments.PushNumber(event.vecPosition.fZ); arguments.PushNumber(event.iModel); arguments.PushNumber(event.iColSurface); - pVehicle->CallEvent("onClientVehicleWeaponHit", arguments, false); + pVehicle->CallEvent(BuiltInEvents::onClientVehicleWeaponHit, arguments, false); } void CClientGame::UpdateDiscordState() diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index 7633479508e..3f4c4d9a4a5 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -33,7 +33,6 @@ #include "lua/CLuaManager.h" #include "CScriptDebugging.h" #include "CZoneNames.h" -#include "CEvents.h" #include "CResourceManager.h" #include "CScriptKeyBinds.h" #include "CElementDeleter.h" @@ -280,7 +279,6 @@ class CClientGame CServerInfo* GetServerInfo() { return m_ServerInfo.get(); } CClientEntity* GetRootEntity() { return m_pRootEntity; } - CEvents* GetEvents() { return &m_Events; } CBlendedWeather* GetBlendedWeather() { return m_pBlendedWeather; }; CNetAPI* GetNetAPI() { return m_pNetAPI; }; @@ -367,8 +365,6 @@ class CClientGame CClientPlayer* GetClosestRemotePlayer(const CVector& vecTemp, float fMaxDistance); - void AddBuiltInEvents(); - const char* GetModRoot() { return m_strModRoot; }; void SetGameSpeed(float fSpeed); @@ -808,7 +804,6 @@ class CClientGame void UpdateDiscordState(); // If netc allows this function not to be here it would be better private: - CEvents m_Events; std::list m_ScreenShotArgList; ushort m_usNextScreenShotId; std::list m_DelayedSendList; diff --git a/Client/mods/deathmatch/logic/CClientMarker.cpp b/Client/mods/deathmatch/logic/CClientMarker.cpp index d4a7bc15e09..92ef156be92 100644 --- a/Client/mods/deathmatch/logic/CClientMarker.cpp +++ b/Client/mods/deathmatch/logic/CClientMarker.cpp @@ -411,7 +411,7 @@ void CClientMarker::Callback_OnCollision(CClientColShape& Shape, CClientEntity& CLuaArguments Arguments; Arguments.PushElement(&Entity); // player that hit it Arguments.PushBoolean((GetDimension() == Entity.GetDimension())); // matching dimension? - CallEvent("onClientMarkerHit", Arguments, true); + CallEvent(BuiltInEvents::onClientMarkerHit, Arguments, true); } } @@ -423,7 +423,7 @@ void CClientMarker::Callback_OnLeave(CClientColShape& Shape, CClientEntity& Enti CLuaArguments Arguments; Arguments.PushElement(&Entity); // player that hit it Arguments.PushBoolean((GetDimension() == Entity.GetDimension())); // matching dimension? - CallEvent("onClientMarkerLeave", Arguments, true); + CallEvent(BuiltInEvents::onClientMarkerLeave, Arguments, true); } } diff --git a/Client/mods/deathmatch/logic/CClientModel.cpp b/Client/mods/deathmatch/logic/CClientModel.cpp index 8e7a7fe4e48..625f267b295 100644 --- a/Client/mods/deathmatch/logic/CClientModel.cpp +++ b/Client/mods/deathmatch/logic/CClientModel.cpp @@ -87,7 +87,7 @@ void CClientModel::RestoreEntitiesUsingThisModel() CLuaArguments Arguments; Arguments.PushNumber(m_iModelID); Arguments.PushNumber(usParentID); - element.CallEvent("onClientElementModelChange", Arguments, true); + element.CallEvent(BuiltInEvents::onClientElementModelChange, Arguments, true); } }; diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index f84aba20f72..ce69634301e 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -4690,7 +4690,7 @@ bool CClientPed::SetCurrentRadioChannel(unsigned char ucChannel) { CLuaArguments Arguments; Arguments.PushNumber(ucChannel); - if (!CallEvent("onClientPlayerRadioSwitch", Arguments, true)) + if (!CallEvent(BuiltInEvents::onClientPlayerRadioSwitch, Arguments, true)) { // if we cancel the radio channel setting at 12 then when they go through previous it will get to 0, then the next time it is used set to 13 in // preperation to set to 12 but if it is cancelled it stays at 13. Issue 6113 - Caz @@ -4955,7 +4955,7 @@ void CClientPed::DestroySatchelCharges(bool bBlow, bool bDestroy) Arguments.PushNumber(vecPosition.fY); Arguments.PushNumber(vecPosition.fZ); Arguments.PushNumber(EXP_TYPE_GRENADE); - bool bCancelExplosion = !CallEvent("onClientExplosion", Arguments, true); + bool bCancelExplosion = !CallEvent(BuiltInEvents::onClientExplosion, Arguments, true); if (!bCancelExplosion) m_pManager->GetExplosionManager()->Create(EXP_TYPE_GRENADE, vecPosition, this, true, -1.0f, false, WEAPONTYPE_REMOTE_SATCHEL_CHARGE); @@ -6560,7 +6560,7 @@ bool CClientPed::EnterVehicle(CClientVehicle* pVehicle, bool bPassenger) Arguments.PushNumber(uiSeat); // seat Arguments.PushNumber(uiDoor); // door - if (!pVehicle->CallEvent("onClientVehicleStartEnter", Arguments, true)) + if (!pVehicle->CallEvent(BuiltInEvents::onClientVehicleStartEnter, Arguments, true)) { // Event has been cancelled return false; diff --git a/Client/mods/deathmatch/logic/CClientPickup.cpp b/Client/mods/deathmatch/logic/CClientPickup.cpp index 37973e80c3d..262c5d9d473 100644 --- a/Client/mods/deathmatch/logic/CClientPickup.cpp +++ b/Client/mods/deathmatch/logic/CClientPickup.cpp @@ -211,13 +211,13 @@ void CClientPickup::Callback_OnCollision(CClientColShape& Shape, CClientEntity& CLuaArguments Arguments; Arguments.PushElement(&Entity); // The element that hit the pickup Arguments.PushBoolean(bMatchingDimensions); - CallEvent("onClientPickupHit", Arguments, true); + CallEvent(BuiltInEvents::onClientPickupHit, Arguments, true); // Call the player pickup hit (source = player that hit the pickup) CLuaArguments Arguments2; Arguments2.PushElement(this); // The pickup that was hit Arguments2.PushBoolean(bMatchingDimensions); - Entity.CallEvent("onClientPlayerPickupHit", Arguments2, true); + Entity.CallEvent(BuiltInEvents::onClientPlayerPickupHit, Arguments2, true); } } @@ -231,12 +231,12 @@ void CClientPickup::Callback_OnLeave(CClientColShape& Shape, CClientEntity& Enti CLuaArguments Arguments; Arguments.PushElement(&Entity); // The element that left the pickup Arguments.PushBoolean(bMatchingDimensions); - CallEvent("onClientPickupLeave", Arguments, true); + CallEvent(BuiltInEvents::onClientPickupLeave, Arguments, true); // Call the player pickup leave event (source = the player that left the pickup) CLuaArguments Arguments2; Arguments2.PushElement(this); // The pickup that was left (this) Arguments2.PushBoolean(bMatchingDimensions); - Entity.CallEvent("onClientPlayerPickupLeave", Arguments2, true); + Entity.CallEvent(BuiltInEvents::onClientPlayerPickupLeave, Arguments2, true); } } diff --git a/Client/mods/deathmatch/logic/CClientPlayerVoice.cpp b/Client/mods/deathmatch/logic/CClientPlayerVoice.cpp index 76dddf16bf5..963e3c671b0 100644 --- a/Client/mods/deathmatch/logic/CClientPlayerVoice.cpp +++ b/Client/mods/deathmatch/logic/CClientPlayerVoice.cpp @@ -60,7 +60,7 @@ void CALLBACK BASS_VoiceStateChange(HSYNC handle, DWORD channel, DWORD data, voi if (pVoice->m_bVoiceActive) { - pVoice->m_EventQueue.push_back("onClientPlayerVoiceStop"); + pVoice->m_EventQueue.push_back(&BuiltInEvents::onClientPlayerVoiceStop); pVoice->m_bVoiceActive = false; } } @@ -129,7 +129,7 @@ void CClientPlayerVoice::DecodeAndBuffer(char* pBuffer, unsigned int bytesWritte ServiceEventQueue(); CLuaArguments Arguments; - if (!m_pPlayer->CallEvent("onClientPlayerVoiceStart", Arguments, true)) + if (!m_pPlayer->CallEvent(BuiltInEvents::onClientPlayerVoiceStart, Arguments, true)) return; m_bVoiceActive = true; @@ -155,17 +155,14 @@ void CClientPlayerVoice::DecodeAndBuffer(char* pBuffer, unsigned int bytesWritte void CClientPlayerVoice::ServiceEventQueue() { - std::list eventQueue; + std::list eventQueue; { std::lock_guard lock(m_Mutex); std::swap(eventQueue, m_EventQueue); } - for (const SString& strEvent : eventQueue) - { - CLuaArguments Arguments; - m_pPlayer->CallEvent(strEvent, Arguments, true); - } + for (auto* event : eventQueue) + m_pPlayer->CallEvent(*event, {}, true); } //////////////////////////////////////////////////////////// @@ -430,14 +427,14 @@ void CClientPlayerVoice::SetPaused(bool bPaused) // call onClientPlayerVoicePause CLuaArguments Arguments; Arguments.PushString("paused"); // Reason - m_pPlayer->CallEvent("onClientPlayerVoicePause", Arguments, false); + m_pPlayer->CallEvent(BuiltInEvents::onClientPlayerVoicePause, Arguments, false); } else { // call onClientPlayerVoiceResumed CLuaArguments Arguments; Arguments.PushString("resumed"); // Reason - m_pPlayer->CallEvent("onClientPlayerVoiceResumed", Arguments, false); + m_pPlayer->CallEvent(BuiltInEvents::onClientPlayerVoiceResumed, Arguments, false); } } diff --git a/Client/mods/deathmatch/logic/CClientPlayerVoice.h b/Client/mods/deathmatch/logic/CClientPlayerVoice.h index 39ce38121d7..04553a79fd3 100644 --- a/Client/mods/deathmatch/logic/CClientPlayerVoice.h +++ b/Client/mods/deathmatch/logic/CClientPlayerVoice.h @@ -33,8 +33,8 @@ class CClientPlayerVoice bool m_bVoiceActive; - std::list m_EventQueue; - std::mutex m_Mutex; // Only for m_EventQueue and m_bVoiceActive + std::list m_EventQueue; + std::mutex m_Mutex; // Only for m_EventQueue and m_bVoiceActive void GetTempoValues(float& fSampleRate, float& fTempo, float& fPitch, bool& bReverse) { diff --git a/Client/mods/deathmatch/logic/CClientSound.cpp b/Client/mods/deathmatch/logic/CClientSound.cpp index d6a214d8e6d..3fa9b8365d8 100644 --- a/Client/mods/deathmatch/logic/CClientSound.cpp +++ b/Client/mods/deathmatch/logic/CClientSound.cpp @@ -69,7 +69,7 @@ void CClientSound::DistanceStreamIn() // Call Stream In event CLuaArguments Arguments; - CallEvent("onClientElementStreamIn", Arguments, true); + CallEvent(BuiltInEvents::onClientElementStreamIn, Arguments, true); } } } @@ -90,7 +90,7 @@ void CClientSound::DistanceStreamOut() // Call Stream Out event CLuaArguments Arguments; - CallEvent("onClientElementStreamOut", Arguments, true); + CallEvent(BuiltInEvents::onClientElementStreamOut, Arguments, true); } } @@ -461,14 +461,14 @@ void CClientSound::SetPaused(bool bPaused) // call onClientSoundStopped CLuaArguments Arguments; Arguments.PushString("paused"); // Reason - this->CallEvent("onClientSoundStopped", Arguments, false); + this->CallEvent(BuiltInEvents::onClientSoundStopped, Arguments, false); } else { // call onClientSoundStarted CLuaArguments Arguments; Arguments.PushString("resumed"); // Reason - this->CallEvent("onClientSoundStarted", Arguments, false); + this->CallEvent(BuiltInEvents::onClientSoundStarted, Arguments, false); } } @@ -685,7 +685,7 @@ void CClientSound::Process3D(const CVector& vecPlayerPosition, const CVector& ve { CLuaArguments Arguments; Arguments.PushString("enabled"); // Reason - CallEvent("onClientSoundStarted", Arguments, false); + CallEvent(BuiltInEvents::onClientSoundStarted, Arguments, false); } } } @@ -695,7 +695,7 @@ void CClientSound::Process3D(const CVector& vecPlayerPosition, const CVector& ve Destroy(); CLuaArguments Arguments; Arguments.PushString("disabled"); // Reason - CallEvent("onClientSoundStopped", Arguments, false); + CallEvent(BuiltInEvents::onClientSoundStopped, Arguments, false); } } @@ -714,14 +714,14 @@ void CClientSound::Process3D(const CVector& vecPlayerPosition, const CVector& ve { CLuaArguments Arguments; Arguments.PushNumber(eventInfo.dNumber); - CallEvent("onClientSoundFinishedDownload", Arguments, true); + CallEvent(BuiltInEvents::onClientSoundFinishedDownload, Arguments, true); OutputDebugLine(SString("[ClientSound] onClientSoundFinishedDownload %f", eventInfo.dNumber)); } else if (eventInfo.type == SOUND_EVENT_CHANGED_META) { CLuaArguments Arguments; Arguments.PushString(eventInfo.strString); - CallEvent("onClientSoundChangedMeta", Arguments, true); + CallEvent(BuiltInEvents::onClientSoundChangedMeta, Arguments, true); OutputDebugLine(SString("[ClientSound] onClientSoundChangedMeta %s", *eventInfo.strString)); } else if (eventInfo.type == SOUND_EVENT_STREAM_RESULT) @@ -732,7 +732,7 @@ void CClientSound::Process3D(const CVector& vecPlayerPosition, const CVector& ve Arguments.PushNumber(eventInfo.dNumber); Arguments.PushString(eventInfo.strString); Arguments.PushString(eventInfo.strError); - CallEvent("onClientSoundStream", Arguments, true); + CallEvent(BuiltInEvents::onClientSoundStream, Arguments, true); OutputDebugLine( SString("[ClientSound] onClientSoundStream %d %f %s %s", eventInfo.bBool, eventInfo.dNumber, *eventInfo.strString, *eventInfo.strError)); } @@ -740,7 +740,7 @@ void CClientSound::Process3D(const CVector& vecPlayerPosition, const CVector& ve { CLuaArguments Arguments; Arguments.PushNumber(eventInfo.dNumber); - CallEvent("onClientSoundBeat", Arguments, true); + CallEvent(BuiltInEvents::onClientSoundBeat, Arguments, true); } } } diff --git a/Client/mods/deathmatch/logic/CClientSoundManager.cpp b/Client/mods/deathmatch/logic/CClientSoundManager.cpp index 698aee23a2e..44af66d7ce3 100644 --- a/Client/mods/deathmatch/logic/CClientSoundManager.cpp +++ b/Client/mods/deathmatch/logic/CClientSoundManager.cpp @@ -110,7 +110,7 @@ void CClientSoundManager::DoPulse() // call onClientSoundStopped CLuaArguments Arguments; Arguments.PushString("finished"); // Reason - pSound->CallEvent("onClientSoundStopped", Arguments, false); + pSound->CallEvent(BuiltInEvents::onClientSoundStopped, Arguments, false); g_pClientGame->GetElementDeleter()->Delete(pSound); } } diff --git a/Client/mods/deathmatch/logic/CClientStreamElement.cpp b/Client/mods/deathmatch/logic/CClientStreamElement.cpp index b883eb0ec7e..389ba245222 100644 --- a/Client/mods/deathmatch/logic/CClientStreamElement.cpp +++ b/Client/mods/deathmatch/logic/CClientStreamElement.cpp @@ -84,7 +84,7 @@ void CClientStreamElement::InternalStreamOut() } CLuaArguments Arguments; - CallEvent("onClientElementStreamOut", Arguments, true); + CallEvent(BuiltInEvents::onClientElementStreamOut, Arguments, true); } } @@ -99,7 +99,7 @@ void CClientStreamElement::NotifyCreate() m_bAttemptingToStreamIn = false; CLuaArguments Arguments; - CallEvent("onClientElementStreamIn", Arguments, true); + CallEvent(BuiltInEvents::onClientElementStreamIn, Arguments, true); } void CClientStreamElement::NotifyUnableToCreate() diff --git a/Client/mods/deathmatch/logic/CClientVehicle.cpp b/Client/mods/deathmatch/logic/CClientVehicle.cpp index 81cae858c2f..93c7650581c 100644 --- a/Client/mods/deathmatch/logic/CClientVehicle.cpp +++ b/Client/mods/deathmatch/logic/CClientVehicle.cpp @@ -2521,7 +2521,7 @@ void CClientVehicle::StreamedInPulse() { CLuaArguments Arguments; Arguments.PushBoolean(bActivated); - this->CallEvent("onClientVehicleNitroStateChange", Arguments, false); + this->CallEvent(BuiltInEvents::onClientVehicleNitroStateChange, Arguments, false); } m_bNitroActivated = bActivated; diff --git a/Client/mods/deathmatch/logic/CClientWeapon.cpp b/Client/mods/deathmatch/logic/CClientWeapon.cpp index 028d6f30146..346d61e648e 100644 --- a/Client/mods/deathmatch/logic/CClientWeapon.cpp +++ b/Client/mods/deathmatch/logic/CClientWeapon.cpp @@ -425,7 +425,7 @@ void CClientWeapon::FireInstantHit(CVector vecOrigin, CVector vecTarget, bool bS Arguments.PushNumber(pColPoint->GetSurfaceTypeB()); // Surface type "B" Arguments.PushNumber(pColPoint->GetLightingForTimeOfDay()); // Lighting Arguments.PushNumber(pColPoint->GetPieceTypeB()); // Piece - if (!CallEvent("onClientWeaponFire", Arguments, true)) + if (!CallEvent(BuiltInEvents::onClientWeaponFire, Arguments, true)) { if (pColPoint) pColPoint->Destroy(); diff --git a/Client/mods/deathmatch/logic/CClientWebBrowser.cpp b/Client/mods/deathmatch/logic/CClientWebBrowser.cpp index bd8b0d61359..cad2d04157a 100644 --- a/Client/mods/deathmatch/logic/CClientWebBrowser.cpp +++ b/Client/mods/deathmatch/logic/CClientWebBrowser.cpp @@ -174,7 +174,7 @@ void CClientWebBrowser::Refresh(bool bIgnoreCache) void CClientWebBrowser::Events_OnCreated() { CLuaArguments Arguments; - CallEvent("onClientBrowserCreated", Arguments, false); + CallEvent(BuiltInEvents::onClientBrowserCreated, Arguments, false); } void CClientWebBrowser::Events_OnLoadingStart(const SString& strURL, bool bMainFrame) @@ -182,14 +182,14 @@ void CClientWebBrowser::Events_OnLoadingStart(const SString& strURL, bool bMainF CLuaArguments Arguments; Arguments.PushString(strURL); Arguments.PushBoolean(bMainFrame); - CallEvent("onClientBrowserLoadingStart", Arguments, false); + CallEvent(BuiltInEvents::onClientBrowserLoadingStart, Arguments, false); } void CClientWebBrowser::Events_OnDocumentReady(const SString& strURL) { CLuaArguments Arguments; Arguments.PushString(strURL); - CallEvent("onClientBrowserDocumentReady", Arguments, false); + CallEvent(BuiltInEvents::onClientBrowserDocumentReady, Arguments, false); } void CClientWebBrowser::Events_OnLoadingFailed(const SString& strURL, int errorCode, const SString& errorDescription) @@ -198,7 +198,7 @@ void CClientWebBrowser::Events_OnLoadingFailed(const SString& strURL, int errorC Arguments.PushString(strURL); Arguments.PushNumber(errorCode); Arguments.PushString(errorDescription); - CallEvent("onClientBrowserLoadingFailed", Arguments, false); + CallEvent(BuiltInEvents::onClientBrowserLoadingFailed, Arguments, false); } void CClientWebBrowser::Events_OnNavigate(const SString& strURL, bool bIsBlocked, bool bIsMainFrame) @@ -207,7 +207,7 @@ void CClientWebBrowser::Events_OnNavigate(const SString& strURL, bool bIsBlocked Arguments.PushString(strURL); Arguments.PushBoolean(bIsBlocked); Arguments.PushBoolean(bIsMainFrame); - CallEvent("onClientBrowserNavigate", Arguments, false); + CallEvent(BuiltInEvents::onClientBrowserNavigate, Arguments, false); } void CClientWebBrowser::Events_OnPopup(const SString& strTargetURL, const SString& strOpenerURL) @@ -215,40 +215,39 @@ void CClientWebBrowser::Events_OnPopup(const SString& strTargetURL, const SStrin CLuaArguments Arguments; Arguments.PushString(strTargetURL); Arguments.PushString(strOpenerURL); - CallEvent("onClientBrowserPopup", Arguments, false); + CallEvent(BuiltInEvents::onClientBrowserPopup, Arguments, false); } void CClientWebBrowser::Events_OnChangeCursor(unsigned char ucCursor) { CLuaArguments Arguments; Arguments.PushNumber(ucCursor); - CallEvent("onClientBrowserCursorChange", Arguments, false); + CallEvent(BuiltInEvents::onClientBrowserCursorChange, Arguments, false); } void CClientWebBrowser::Events_OnTriggerEvent(const SString& strEventName, const std::vector& arguments) { - CLuaArguments Arguments; - for (std::vector::const_iterator iter = arguments.begin(); iter != arguments.end(); ++iter) + if (auto* event = Event::Get(strEventName)) { - Arguments.PushString(*iter); + CLuaArguments luaargs; + for (auto& arg : arguments) + luaargs.PushString(arg); + CallEvent(*event, luaargs, true); } - - bool bWasCancelled; - CStaticFunctionDefinitions::TriggerEvent(strEventName, *this, Arguments, bWasCancelled); } void CClientWebBrowser::Events_OnTooltip(const SString& strTooltip) { CLuaArguments Arguments; Arguments.PushString(strTooltip); - CallEvent("onClientBrowserTooltip", Arguments, false); + CallEvent(BuiltInEvents::onClientBrowserTooltip, Arguments, false); } void CClientWebBrowser::Events_OnInputFocusChanged(bool bGainedFocus) { CLuaArguments Arguments; Arguments.PushBoolean(bGainedFocus); - CallEvent("onClientBrowserInputFocusChanged", Arguments, false); + CallEvent(BuiltInEvents::onClientBrowserInputFocusChanged, Arguments, false); } bool CClientWebBrowser::Events_OnResourcePathCheck(SString& strURL) @@ -287,7 +286,7 @@ void CClientWebBrowser::Events_OnResourceBlocked(const SString& strURL, const SS Arguments.PushString(strURL); Arguments.PushString(strDomain); Arguments.PushNumber(reason); - CallEvent("onClientBrowserResourceBlocked", Arguments, false); + CallEvent(BuiltInEvents::onClientBrowserResourceBlocked, Arguments, false); } void CClientWebBrowser::Events_OnAjaxRequest(CAjaxResourceHandlerInterface* pHandler, const SString& strURL) diff --git a/Client/mods/deathmatch/logic/CDeathmatchObject.cpp b/Client/mods/deathmatch/logic/CDeathmatchObject.cpp index c1712246fb9..c1e104fd3ec 100644 --- a/Client/mods/deathmatch/logic/CDeathmatchObject.cpp +++ b/Client/mods/deathmatch/logic/CDeathmatchObject.cpp @@ -70,7 +70,7 @@ void CDeathmatchObject::StartMovement(const CPositionRotationAnimation& a_rMoveA SetOrientation(positionRotation.m_vecPosition, positionRotation.m_vecRotation); } CLuaArguments Arguments; - this->CallEvent("onClientObjectMoveStart", Arguments, true); + this->CallEvent(BuiltInEvents::onClientObjectMoveStart, Arguments, true); } void CDeathmatchObject::StopMovement() @@ -89,7 +89,7 @@ void CDeathmatchObject::_StopMovement(bool a_bUnregister) delete m_pMoveAnimation; m_pMoveAnimation = NULL; CLuaArguments Arguments; - this->CallEvent("onClientObjectMoveStop", Arguments, true); + this->CallEvent(BuiltInEvents::onClientObjectMoveStop, Arguments, true); } } diff --git a/Client/mods/deathmatch/logic/CElementDeleter.cpp b/Client/mods/deathmatch/logic/CElementDeleter.cpp index 147fa4835a2..8f39d46b98d 100644 --- a/Client/mods/deathmatch/logic/CElementDeleter.cpp +++ b/Client/mods/deathmatch/logic/CElementDeleter.cpp @@ -26,7 +26,7 @@ void CElementDeleter::Delete(class CClientEntity* pElement) { // Before we do anything, fire the on-destroy event CLuaArguments Arguments; - pElement->CallEvent("onClientElementDestroy", Arguments, true); + pElement->CallEvent(BuiltInEvents::onClientElementDestroy, Arguments, true); // Add it to our list if (!pElement->IsBeingDeleted()) diff --git a/Client/mods/deathmatch/logic/CEvents.cpp b/Client/mods/deathmatch/logic/CEvents.cpp deleted file mode 100644 index a62f39e2e5b..00000000000 --- a/Client/mods/deathmatch/logic/CEvents.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/***************************************************************************** - * - * PROJECT: Multi Theft Auto v1.0 - * (Shared logic for modifications) - * LICENSE: See LICENSE in the top level directory - * FILE: mods/shared_logic/CEvents.cpp - * PURPOSE: Events class - * - *****************************************************************************/ - -#include "StdInc.h" - -using std::list; - -CEvents::CEvents() -{ - m_bWasEventCancelled = false; - m_bEventCancelled = false; -} - -CEvents::~CEvents() -{ - RemoveAllEvents(); -} - -bool CEvents::AddEvent(const char* szName, const char* szArguments, CLuaMain* pLuaMain, bool bAllowRemoteTrigger) -{ - assert(szName); - assert(szArguments); - - // If it already exists, return - if (Get(szName)) - return false; - - // Create and add the event - SEvent* pEvent = new SEvent; - pEvent->strName = szName; - pEvent->strArguments = szArguments; - pEvent->pLuaMain = pLuaMain; - pEvent->bAllowRemoteTrigger = bAllowRemoteTrigger; - - m_EventHashMap[szName] = pEvent; - - return true; -} - -void CEvents::RemoveEvent(SEvent* pEvent) -{ - assert(pEvent); - - // Remove it and delete it - if (!m_EventHashMap.empty()) - { - MapRemove(m_EventHashMap, pEvent->strName); - } - delete pEvent; -} - -void CEvents::RemoveEvent(const char* szName) -{ - assert(szName); - - // Find it - SEvent* pEvent = Get(szName); - if (pEvent) - { - // Delete it - if (!m_EventHashMap.empty()) - { - MapRemove(m_EventHashMap, pEvent->strName); - } - delete pEvent; - } -} - -void CEvents::RemoveAllEvents(class CLuaMain* pMain) -{ - // Delete all items - CFastHashMap::iterator iter = m_EventHashMap.begin(); - while (iter != m_EventHashMap.end()) - { - SEvent* pEvent = (*iter).second; - // If they match, delete it null it and set the bool - if (pEvent != NULL && pEvent->pLuaMain == pMain) - { - // Delete the object - delete pEvent; - - // Remove from list - m_EventHashMap.erase(iter++); - } - else - ++iter; - } -} - -SEvent* CEvents::Get(const char* szName) -{ - assert(szName); - - SEvent** pEvent = MapFind(m_EventHashMap, szName); - if (pEvent != NULL) - { - return *pEvent; - } - return NULL; -} - -void CEvents::RemoveAllEvents() -{ - // Delete all items - CFastHashMap::const_iterator iter = m_EventHashMap.begin(); - for (; iter != m_EventHashMap.end(); iter++) - { - SEvent* pEvent = (*iter).second; - delete pEvent; - } - - m_EventHashMap.clear(); -} - -void CEvents::PreEventPulse() -{ - m_CancelledList.push_back(m_bEventCancelled); - m_bEventCancelled = false; - m_bWasEventCancelled = false; -} - -void CEvents::PostEventPulse() -{ - m_bWasEventCancelled = m_bEventCancelled; - m_bEventCancelled = m_CancelledList.back() ? true : false; - m_CancelledList.pop_back(); -} - -void CEvents::CancelEvent(bool bCancelled) -{ - m_bEventCancelled = bCancelled; -} - -bool CEvents::WasEventCancelled() -{ - return m_bWasEventCancelled; -} diff --git a/Client/mods/deathmatch/logic/CEvents.h b/Client/mods/deathmatch/logic/CEvents.h deleted file mode 100644 index e5a5ede8ec8..00000000000 --- a/Client/mods/deathmatch/logic/CEvents.h +++ /dev/null @@ -1,55 +0,0 @@ -/***************************************************************************** - * - * PROJECT: Multi Theft Auto v1.0 - * (Shared logic for modifications) - * LICENSE: See LICENSE in the top level directory - * FILE: mods/shared_logic/CEvents.h - * PURPOSE: Events class header - * - *****************************************************************************/ - -#pragma once - -#include -#include -#include - -struct SEvent -{ - class CLuaMain* pLuaMain; - std::string strName; - std::string strArguments; - bool bAllowRemoteTrigger; -}; - -class CEvents -{ -public: - CEvents(); - ~CEvents(); - - bool AddEvent(const char* szName, const char* szArguments, class CLuaMain* pLuaMain, bool bAllowRemoteTrigger); - void RemoveEvent(SEvent* pEvent); - void RemoveEvent(const char* szName); - void RemoveAllEvents(class CLuaMain* pMain); - - bool Exists(const char* szName) { return Get(szName) != NULL; }; - SEvent* Get(const char* szName); - - CFastHashMap::const_iterator IterBegin() { return m_EventHashMap.begin(); }; - CFastHashMap::const_iterator IterEnd() { return m_EventHashMap.end(); }; - - void PreEventPulse(); - void PostEventPulse(); - - void CancelEvent(bool bCancelled = true); - bool WasEventCancelled(); - -private: - void RemoveAllEvents(); - - CFastHashMap m_EventHashMap; - std::vector m_CancelledList; - bool m_bEventCancelled; - bool m_bWasEventCancelled; -}; diff --git a/Client/mods/deathmatch/logic/CMapEvent.cpp b/Client/mods/deathmatch/logic/CMapEvent.cpp deleted file mode 100644 index 3754b042f8e..00000000000 --- a/Client/mods/deathmatch/logic/CMapEvent.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/***************************************************************************** - * - * PROJECT: Multi Theft Auto v1.0 - * (Shared logic for modifications) - * LICENSE: See LICENSE in the top level directory - * FILE: mods/shared_logic/CMapEvent.cpp - * PURPOSE: Map event class - * - *****************************************************************************/ - -#include - -CMapEvent::CMapEvent(CLuaMain* pMain, const char* szName, const CLuaFunctionRef& iLuaFunction, bool bPropagated, EEventPriorityType eventPriority, - float fPriorityMod) -{ - // Init - m_pMain = pMain; - m_bDestroyFunction = false; - m_iLuaFunction = iLuaFunction; - m_bPropagated = bPropagated; - m_bBeingDestroyed = false; - m_eventPriority = eventPriority; - m_fPriorityMod = fPriorityMod; - m_strName.AssignLeft(szName, MAPEVENT_MAX_LENGTH_NAME); - // Only allow dxSetAspectRatioAdjustmentEnabled during these events - m_bAllowAspectRatioAdjustment = (m_strName == "onClientRender") || (m_strName == "onClientPreRender") || (m_strName == "onClientHUDRender"); - // Force aspect ratio adjustment for 'customblips' resource - m_bForceAspectRatioAdjustment = m_bAllowAspectRatioAdjustment && SStringX(pMain->GetScriptName()) == "customblips"; -} - -CMapEvent::~CMapEvent() -{ -} - -void CMapEvent::Call(const CLuaArguments& Arguments) -{ - if (m_pMain) - { - // Call our function with the given arguments - Arguments.Call(m_pMain, m_iLuaFunction); - } -} - -bool CMapEvent::IsHigherPriorityThan(const CMapEvent* pOther) -{ - return m_eventPriority > pOther->m_eventPriority || (m_eventPriority == pOther->m_eventPriority && m_fPriorityMod > pOther->m_fPriorityMod); -} diff --git a/Client/mods/deathmatch/logic/CMapEvent.h b/Client/mods/deathmatch/logic/CMapEvent.h deleted file mode 100644 index 152aa67ba8e..00000000000 --- a/Client/mods/deathmatch/logic/CMapEvent.h +++ /dev/null @@ -1,50 +0,0 @@ -/***************************************************************************** - * - * PROJECT: Multi Theft Auto v1.0 - * (Shared logic for modifications) - * LICENSE: See LICENSE in the top level directory - * FILE: mods/shared_logic/CMapEvent.h - * PURPOSE: Map event class header - * - *****************************************************************************/ - -#pragma once - -#define MAPEVENT_MAX_LENGTH_NAME 100 - -#include - -class CMapEvent -{ - friend class CMapEventManager; - -public: - class CLuaMain* GetVM() { return m_pMain; }; - const SString& GetName() { return m_strName; }; - CLuaFunctionRef GetLuaFunction() { return m_iLuaFunction; }; - bool IsBeingDestroyed() { return m_bBeingDestroyed; } - bool IsPropagated() { return m_bPropagated; } - bool ShouldAllowAspectRatioAdjustment() { return m_bAllowAspectRatioAdjustment; } - bool ShouldForceAspectRatioAdjustment() { return m_bForceAspectRatioAdjustment; } - - void Call(const class CLuaArguments& Arguments); - bool IsHigherPriorityThan(const CMapEvent* pOther); - -private: - CMapEvent(class CLuaMain* pMain, const char* szName, const CLuaFunctionRef& iLuaFunction, bool bPropagated, EEventPriorityType eventPriority, - float fPriorityMod); - ~CMapEvent(); - - void SetBeingDestroyed(bool bBeingDestroyed) { m_bBeingDestroyed = bBeingDestroyed; } - - class CLuaMain* m_pMain; - CLuaFunctionRef m_iLuaFunction; - SString m_strName; - bool m_bDestroyFunction; - bool m_bPropagated; - bool m_bBeingDestroyed; - EEventPriorityType m_eventPriority; - float m_fPriorityMod; - bool m_bAllowAspectRatioAdjustment; - bool m_bForceAspectRatioAdjustment; -}; diff --git a/Client/mods/deathmatch/logic/CMapEventManager.cpp b/Client/mods/deathmatch/logic/CMapEventManager.cpp deleted file mode 100644 index 27042ffa1cb..00000000000 --- a/Client/mods/deathmatch/logic/CMapEventManager.cpp +++ /dev/null @@ -1,403 +0,0 @@ -/***************************************************************************** - * - * PROJECT: Multi Theft Auto v1.0 - * (Shared logic for modifications) - * LICENSE: See LICENSE in the top level directory - * FILE: mods/shared_logic/CMapEventManager.cpp - * PURPOSE: Map event manager class - * - *****************************************************************************/ - -#include "StdInc.h" -bool g_bAllowAspectRatioAdjustment = false; - -CMapEventManager::CMapEventManager() -{ - m_bIteratingList = false; - m_bHasEvents = false; -} - -CMapEventManager::~CMapEventManager() -{ - // If this happens while we're iterating the list, we're screwed - dassert(!m_bIteratingList); - - // This should always be empty when m_bIteratingList is false - dassert(m_TrashCan.empty()); - - // Delete all eventhandlers - DeleteAll(); -} - -bool CMapEventManager::Add(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction, bool bPropagated, EEventPriorityType eventPriority, - float fPriorityMod) -{ - // Check for max name length - if (strlen(szName) <= MAPEVENT_MAX_LENGTH_NAME) - { - // Make a new event - CMapEvent* pEvent = new CMapEvent(pLuaMain, szName, iLuaFunction, bPropagated, eventPriority, fPriorityMod); - - // Add now - AddInternal(pEvent); - - m_bHasEvents = true; - return true; - } - return false; -} - -bool CMapEventManager::Delete(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction) -{ - // Delete all the events with matching names - bool bRemovedSomeone = false; - - EventsIter iter = m_EventsMap.begin(); - while (iter != m_EventsMap.end()) - { - CMapEvent* pMapEvent = iter->second; - - // Matching VM? - if (pLuaMain == pMapEvent->GetVM()) - { - // If name supplied, check name and function - if (!szName || ((strcmp(pMapEvent->GetName(), szName) == 0) && (pMapEvent->GetLuaFunction() == iLuaFunction))) - { - // Not alredy being destroyed? - if (!pMapEvent->IsBeingDestroyed()) - { - // Are we in an event handler? - if (m_bIteratingList) - { - // Put it in the trashcan - pMapEvent->SetBeingDestroyed(true); - m_TrashCan.push_back(pMapEvent); - - // Remember that we deleted something - bRemovedSomeone = true; - } - else - { - // Delete the object - delete pMapEvent; - - // Remove from list and remember that we deleted something - m_EventsMap.erase(iter++); - bRemovedSomeone = true; - continue; - } - } - } - } - - // Increment iterator - ++iter; - } - - m_bHasEvents = !m_EventsMap.empty(); - - // Return whether we actually destroyed someone or not - return bRemovedSomeone; -} - -void CMapEventManager::DeleteAll() -{ - // Delete all the events - EventsIter iter = m_EventsMap.begin(); - while (iter != m_EventsMap.end()) - { - CMapEvent* pMapEvent = iter->second; - - // Delete it if it's not already being destroyed - if (!pMapEvent->IsBeingDestroyed()) - { - delete pMapEvent; - m_EventsMap.erase(iter++); - } - else - ++iter; - } - m_bHasEvents = !m_EventsMap.empty(); -} - -bool CMapEventManager::Call(const char* szName, const CLuaArguments& Arguments, class CClientEntity* pSource, class CClientEntity* pThis) -{ - // Check if no events - if (!m_bHasEvents) - return false; - - // Check if no events with a name match - EventsIterPair itPair = m_EventsMap.equal_range(szName); - if (itPair.first == itPair.second) - return false; - - TIMEUS startTimeCall = GetTimeUs(); - SString strStatus; - - // Check for multi-threading slipups - assert(IsMainThread()); - - // Call all the events with matching names - bool bCalled = false; - bool bIsAlreadyIterating = m_bIteratingList; - m_bIteratingList = true; - - // Copy the results into a array in case m_EventsMap is modified during the call - std::vector matchingEvents; - for (EventsIter iter = itPair.first; iter != itPair.second; ++iter) - matchingEvents.push_back(iter->second); - - for (std::vector::iterator iter = matchingEvents.begin(); iter != matchingEvents.end(); ++iter) - { - CMapEvent* pMapEvent = *iter; - - // If it's not being destroyed - if (!pMapEvent->IsBeingDestroyed()) - { - // Compare the names - dassert(strcmp(pMapEvent->GetName(), szName) == 0); - { - // Call if propagated? - if (pSource == pThis || pMapEvent->IsPropagated()) - { - // Grab the current VM - lua_State* pState = pMapEvent->GetVM()->GetVM(); - - LUA_CHECKSTACK(pState, 1); // Ensure some room - - #if MTA_DEBUG - int luaStackPointer = lua_gettop(pState); - #endif - - TIMEUS startTime = GetTimeUs(); - - // Aspect ratio adjustment bodges - if (pMapEvent->ShouldAllowAspectRatioAdjustment()) - { - g_bAllowAspectRatioAdjustment = true; - if (pMapEvent->ShouldForceAspectRatioAdjustment()) - g_pCore->GetGraphics()->SetAspectRatioAdjustmentEnabled(true); - } - - // Record event for the crash dump writer - static bool bEnabled = (g_pCore->GetDiagnosticDebug() == EDiagnosticDebug::LUA_TRACE_0000); - if (bEnabled) - g_pCore->LogEvent(0, "Lua Event", pMapEvent->GetVM()->GetScriptName(), szName); - - if (!g_pClientGame->GetDebugHookManager()->OnPreEventFunction(szName, Arguments, pSource, nullptr, pMapEvent)) - continue; - - // Store the current values of the globals - lua_getglobal(pState, "source"); - CLuaArgument OldSource(pState, -1); - lua_pop(pState, 1); - - lua_getglobal(pState, "this"); - CLuaArgument OldThis(pState, -1); - lua_pop(pState, 1); - - lua_getglobal(pState, "sourceResource"); - CLuaArgument OldResource(pState, -1); - lua_pop(pState, 1); - - lua_getglobal(pState, "sourceResourceRoot"); - CLuaArgument OldResourceRoot(pState, -1); - lua_pop(pState, 1); - - lua_getglobal(pState, "eventName"); - CLuaArgument OldEventName(pState, -1); - lua_pop(pState, 1); - - // Set the "source", "this", "sourceResource" and the "sourceResourceRoot" globals on that VM - lua_pushelement(pState, pSource); - lua_setglobal(pState, "source"); - - lua_pushelement(pState, pThis); - lua_setglobal(pState, "this"); - - CLuaMain* pLuaMain = g_pClientGame->GetScriptDebugging()->GetTopLuaMain(); - CResource* pSourceResource = pLuaMain ? pLuaMain->GetResource() : NULL; - if (pSourceResource) - { - lua_pushresource(pState, pSourceResource); - lua_setglobal(pState, "sourceResource"); - - lua_pushelement(pState, pSourceResource->GetResourceDynamicEntity()); - lua_setglobal(pState, "sourceResourceRoot"); - } - else - { - lua_pushnil(pState); - lua_setglobal(pState, "sourceResource"); - - lua_pushnil(pState); - lua_setglobal(pState, "sourceResourceRoot"); - } - - lua_pushstring(pState, szName); - lua_setglobal(pState, "eventName"); - - // Call it - pMapEvent->Call(Arguments); - bCalled = true; - - g_pClientGame->GetDebugHookManager()->OnPostEventFunction(szName, Arguments, pSource, nullptr, pMapEvent); - - // Reset the globals on that VM - OldSource.Push(pState); - lua_setglobal(pState, "source"); - - OldThis.Push(pState); - lua_setglobal(pState, "this"); - - OldResource.Push(pState); - lua_setglobal(pState, "sourceResource"); - - OldResourceRoot.Push(pState); - lua_setglobal(pState, "sourceResourceRoot"); - - OldEventName.Push(pState); - lua_setglobal(pState, "eventName"); - - #if MTA_DEBUG - assert(lua_gettop(pState) == luaStackPointer); - #endif - - // Aspect ratio adjustment bodges - if (pMapEvent->ShouldAllowAspectRatioAdjustment()) - { - g_pCore->GetGraphics()->SetAspectRatioAdjustmentEnabled(false); - g_bAllowAspectRatioAdjustment = false; - } - - TIMEUS deltaTimeUs = GetTimeUs() - startTime; - - if (deltaTimeUs > 3000) - if (IS_TIMING_CHECKPOINTS()) - strStatus += SString(" (%s %d ms)", pMapEvent->GetVM()->GetScriptName(), deltaTimeUs / 1000); - - CClientPerfStatLuaTiming::GetSingleton()->UpdateLuaTiming(pMapEvent->GetVM(), szName, deltaTimeUs); - } - } - } - } - - // Clean out the trash if we're no longer calling events. - if (!bIsAlreadyIterating) - { - TakeOutTheTrash(); - - // We're no longer iterating the list - m_bIteratingList = false; - } - - if (IS_TIMING_CHECKPOINTS()) - { - TIMEUS deltaTimeUs = GetTimeUs() - startTimeCall; - if (deltaTimeUs > 5000) - TIMING_DETAIL(SString("CMapEventManager::Call ( %s, ... ) took %d ms ( %s )", szName, deltaTimeUs / 1000, *strStatus)); - } - - // Return whether we called atleast one func or not - return bCalled; -} - -void CMapEventManager::TakeOutTheTrash() -{ - // Loop through our trashcan deleting every item - std::list::const_iterator iterTrash = m_TrashCan.begin(); - for (; iterTrash != m_TrashCan.end(); iterTrash++) - { - CMapEvent* pMapEvent = *iterTrash; - - // Remove from the eventhandler list - EventsIter iterMap = m_EventsMap.begin(); - while (iterMap != m_EventsMap.end()) - { - if (pMapEvent == iterMap->second) - m_EventsMap.erase(iterMap++); - else - ++iterMap; - } - - // Delete it - delete pMapEvent; - } - - m_bHasEvents = !m_EventsMap.empty(); - - // Clear the trashcan - m_TrashCan.clear(); -} - -bool CMapEventManager::HandleExists(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction) -{ - // Return true if we find an event which matches the handle - EventsIterPair itPair = m_EventsMap.equal_range(szName); - for (EventsIter iter = itPair.first; iter != itPair.second; ++iter) - { - CMapEvent* pMapEvent = iter->second; - - // Is it not being destroyed? - if (!pMapEvent->IsBeingDestroyed()) - { - // Same lua main? - if (pMapEvent->GetVM() == pLuaMain) - { - // Same name? - dassert(strcmp(pMapEvent->GetName(), szName) == 0); - { - // Same lua function? - if (pMapEvent->GetLuaFunction() == iLuaFunction) - { - // It exists - return true; - } - } - } - } - } - - // Doesn't exist - return false; -} - -void CMapEventManager::AddInternal(CMapEvent* pEvent) -{ - // Find place to insert - EventsIterPair itPair = m_EventsMap.equal_range(pEvent->GetName()); - EventsIter iter; - for (iter = itPair.first; iter != itPair.second; ++iter) - { - if (pEvent->IsHigherPriorityThan(iter->second)) - break; - } - // Do insert - m_EventsMap.insert(iter, std::pair(pEvent->GetName(), pEvent)); -} - -void CMapEventManager::GetHandles(CLuaMain* pLuaMain, const char* szName, lua_State* luaVM) -{ - unsigned int uiIndex = 0; - EventsIterPair itPair = m_EventsMap.equal_range(szName); - for (EventsIter iter = itPair.first; iter != itPair.second; ++iter) - { - CMapEvent* pMapEvent = iter->second; - - // Is it not being destroyed? - if (!pMapEvent->IsBeingDestroyed()) - { - // Same lua main? - if (pMapEvent->GetVM() == pLuaMain) - { - // Same name? - dassert(strcmp(pMapEvent->GetName(), szName) == 0); - { - lua_pushnumber(luaVM, ++uiIndex); - lua_getref(luaVM, pMapEvent->GetLuaFunction().ToInt()); - lua_settable(luaVM, -3); - } - } - } - } -} \ No newline at end of file diff --git a/Client/mods/deathmatch/logic/CMapEventManager.h b/Client/mods/deathmatch/logic/CMapEventManager.h deleted file mode 100644 index e6500fefdd3..00000000000 --- a/Client/mods/deathmatch/logic/CMapEventManager.h +++ /dev/null @@ -1,46 +0,0 @@ -/***************************************************************************** - * - * PROJECT: Multi Theft Auto v1.0 - * (Shared logic for modifications) - * LICENSE: See LICENSE in the top level directory - * FILE: mods/shared_logic/CMapEventManager.h - * PURPOSE: Map event manager class header - * - *****************************************************************************/ - -#pragma once - -#include "lua/CLuaArguments.h" -#include "CMapEvent.h" -#include - -class CMapEventManager -{ -public: - CMapEventManager(); - ~CMapEventManager(); - - bool Add(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction, bool bPropagated, EEventPriorityType eventPriority, - float fPriorityMod); - bool Delete(CLuaMain* pLuaMain, const char* szName = NULL, const CLuaFunctionRef& iLuaFunction = CLuaFunctionRef()); - void DeleteAll(); - bool HandleExists(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction); - bool HasEvents() const { return m_bHasEvents; } - void GetHandles(CLuaMain* pLuaMain, const char* szName, lua_State* luaVM); - - bool Call(const char* szName, const CLuaArguments& Arguments, class CClientEntity* pSource, class CClientEntity* pThis); - -private: - void TakeOutTheTrash(); - void AddInternal(CMapEvent* pEvent); - - bool m_bHasEvents; - bool m_bIteratingList; - std::multimap m_EventsMap; - std::list m_TrashCan; - - // Types for m_EventsMap access - typedef std::multimap::const_iterator EventsConstIter; - typedef std::multimap::iterator EventsIter; - typedef std::pair EventsIterPair; -}; diff --git a/Client/mods/deathmatch/logic/CPacketHandler.cpp b/Client/mods/deathmatch/logic/CPacketHandler.cpp index c2ed07917f7..9e5365d29c7 100644 --- a/Client/mods/deathmatch/logic/CPacketHandler.cpp +++ b/Client/mods/deathmatch/logic/CPacketHandler.cpp @@ -454,7 +454,7 @@ void CPacketHandler::Packet_ServerJoined(NetBitStreamInterface& bitStream) // Call the onClientPlayerJoin event for ourselves CLuaArguments Arguments; - g_pClientGame->m_pLocalPlayer->CallEvent("onClientPlayerJoin", Arguments, true); + g_pClientGame->m_pLocalPlayer->CallEvent(BuiltInEvents::onClientPlayerJoin, Arguments, true); g_pCore->UpdateRecentlyPlayed(); } @@ -991,7 +991,7 @@ void CPacketHandler::Packet_PlayerList(NetBitStreamInterface& bitStream) { // Call the onClientPlayerJoin event CLuaArguments Arguments; - pPlayer->CallEvent("onClientPlayerJoin", Arguments, true); + pPlayer->CallEvent(BuiltInEvents::onClientPlayerJoin, Arguments, true); } } @@ -1131,7 +1131,7 @@ void CPacketHandler::Packet_PlayerSpawn(NetBitStreamInterface& bitStream) Arguments.PushElement(pTeam); else Arguments.PushBoolean(false); - pPlayer->CallEvent("onClientPlayerSpawn", Arguments, true); + pPlayer->CallEvent(BuiltInEvents::onClientPlayerSpawn, Arguments, true); } } @@ -1205,9 +1205,9 @@ void CPacketHandler::Packet_PlayerWasted(NetBitStreamInterface& bitStream) Arguments.PushBoolean(false); Arguments.PushBoolean(bStealth); if (IS_PLAYER(pPed)) - pPed->CallEvent("onClientPlayerWasted", Arguments, true); + pPed->CallEvent(BuiltInEvents::onClientPlayerWasted, Arguments, true); else - pPed->CallEvent("onClientPedWasted", Arguments, true); + pPed->CallEvent(BuiltInEvents::onClientPedWasted, Arguments, true); } } } @@ -1315,7 +1315,7 @@ void CPacketHandler::Packet_PlayerChangeNick(NetBitStreamInterface& bitStream) { Arguments.PushBoolean(false); } - pPlayer->CallEvent("onClientPlayerChangeNick", Arguments, true); + pPlayer->CallEvent(BuiltInEvents::onClientPlayerChangeNick, Arguments, true); /* * Cleanup. @@ -1381,7 +1381,7 @@ void CPacketHandler::Packet_ChatEcho(NetBitStreamInterface& bitStream) Arguments.PushNumber(ucRed); Arguments.PushNumber(ucGreen); Arguments.PushNumber(ucBlue); - bool bCancelled = !pEntity->CallEvent("onClientChatMessage", Arguments, pEntity != pRootEntity); + bool bCancelled = !pEntity->CallEvent(BuiltInEvents::onClientChatMessage, Arguments, pEntity != pRootEntity); if (!bCancelled) { // Echo it @@ -1571,7 +1571,7 @@ void CPacketHandler::Packet_VehicleSpawn(NetBitStreamInterface& bitStream) // Call the onClientVehicleRespawn event CLuaArguments Arguments; - pVehicle->CallEvent("onClientVehicleRespawn", Arguments, true); + pVehicle->CallEvent(BuiltInEvents::onClientVehicleRespawn, Arguments, true); } } @@ -1691,7 +1691,7 @@ void CPacketHandler::Packet_Vehicle_InOut(NetBitStreamInterface& bitStream) Arguments.PushElement(pPed); // player / ped Arguments.PushNumber(ucSeat); // seat Arguments.PushNumber(ucDoor); // Door - pVehicle->CallEvent("onClientVehicleStartEnter", Arguments, true); + pVehicle->CallEvent(BuiltInEvents::onClientVehicleStartEnter, Arguments, true); } // Start animating him in @@ -1728,15 +1728,15 @@ void CPacketHandler::Packet_Vehicle_InOut(NetBitStreamInterface& bitStream) Arguments.PushElement(pVehicle); // vehicle Arguments.PushNumber(ucSeat); // seat if (IS_PLAYER(pPed)) - pPed->CallEvent("onClientPlayerVehicleEnter", Arguments, true); + pPed->CallEvent(BuiltInEvents::onClientPlayerVehicleEnter, Arguments, true); else - pPed->CallEvent("onClientPedVehicleEnter", Arguments, true); + pPed->CallEvent(BuiltInEvents::onClientPedVehicleEnter, Arguments, true); // Call the onClientVehicleEnter event CLuaArguments Arguments2; Arguments2.PushElement(pPed); // player / ped Arguments2.PushNumber(ucSeat); // seat - pVehicle->CallEvent("onClientVehicleEnter", Arguments2, true); + pVehicle->CallEvent(BuiltInEvents::onClientVehicleEnter, Arguments2, true); break; } @@ -1803,7 +1803,7 @@ void CPacketHandler::Packet_Vehicle_InOut(NetBitStreamInterface& bitStream) Arguments.PushElement(pPed); // player / ped Arguments.PushNumber(ucSeat); // seat Arguments.PushNumber(ucDoor); // door being used - pVehicle->CallEvent("onClientVehicleStartExit", Arguments, true); + pVehicle->CallEvent(BuiltInEvents::onClientVehicleStartExit, Arguments, true); break; } @@ -1829,16 +1829,16 @@ void CPacketHandler::Packet_Vehicle_InOut(NetBitStreamInterface& bitStream) Arguments.PushNumber(ucSeat); // seat Arguments.PushBoolean(false); // jacker if (IS_PLAYER(pPed)) - pPed->CallEvent("onClientPlayerVehicleExit", Arguments, true); + pPed->CallEvent(BuiltInEvents::onClientPlayerVehicleExit, Arguments, true); else - pPed->CallEvent("onClientPedVehicleExit", Arguments, true); + pPed->CallEvent(BuiltInEvents::onClientPedVehicleExit, Arguments, true); // Call the onClientVehicleExit event CLuaArguments Arguments2; Arguments2.PushElement(pPed); // player / ped Arguments2.PushNumber(ucSeat); // seat Arguments2.PushBoolean(false); // jacker - pVehicle->CallEvent("onClientVehicleExit", Arguments2, true); + pVehicle->CallEvent(BuiltInEvents::onClientVehicleExit, Arguments2, true); break; } @@ -1876,16 +1876,16 @@ void CPacketHandler::Packet_Vehicle_InOut(NetBitStreamInterface& bitStream) Arguments.PushNumber(ucSeat); // seat Arguments.PushBoolean(false); // jacker if (IS_PLAYER(pPed)) - pPed->CallEvent("onClientPlayerVehicleExit", Arguments, true); + pPed->CallEvent(BuiltInEvents::onClientPlayerVehicleExit, Arguments, true); else - pPed->CallEvent("onClientPedVehicleExit", Arguments, true); + pPed->CallEvent(BuiltInEvents::onClientPedVehicleExit, Arguments, true); // Call the onClientVehicleExit event CLuaArguments Arguments2; Arguments2.PushElement(pPed); // player / ped Arguments2.PushNumber(ucSeat); // seat Arguments2.PushBoolean(false); // jacker - pVehicle->CallEvent("onClientVehicleExit", Arguments2, true); + pVehicle->CallEvent(BuiltInEvents::onClientVehicleExit, Arguments2, true); break; } @@ -1912,7 +1912,7 @@ void CPacketHandler::Packet_Vehicle_InOut(NetBitStreamInterface& bitStream) Arguments.PushElement(pPed); // player / ped Arguments.PushNumber(ucSeat); // seat Arguments.PushNumber(ucDoor); // Door - pVehicle->CallEvent("onClientVehicleStartEnter", Arguments, true); + pVehicle->CallEvent(BuiltInEvents::onClientVehicleStartEnter, Arguments, true); } if (pJacked) @@ -1938,7 +1938,7 @@ void CPacketHandler::Packet_Vehicle_InOut(NetBitStreamInterface& bitStream) Arguments2.PushElement(pJacked); // player / ped Arguments2.PushNumber(ucSeat); // seat Arguments2.PushNumber(ucDoor); // door - pVehicle->CallEvent("onClientVehicleStartExit", Arguments2, true); + pVehicle->CallEvent(BuiltInEvents::onClientVehicleStartExit, Arguments2, true); break; } @@ -2004,29 +2004,29 @@ void CPacketHandler::Packet_Vehicle_InOut(NetBitStreamInterface& bitStream) CLuaArguments Arguments; Arguments.PushElement(pInsidePed); // player / ped Arguments.PushNumber(ucSeat); // seat - pVehicle->CallEvent("onClientVehicleEnter", Arguments, true); + pVehicle->CallEvent(BuiltInEvents::onClientVehicleEnter, Arguments, true); CLuaArguments Arguments2; Arguments2.PushElement(pOutsidePed); // player / ped Arguments2.PushNumber(ucSeat); // seat - pVehicle->CallEvent("onClientVehicleExit", Arguments2, true); + pVehicle->CallEvent(BuiltInEvents::onClientVehicleExit, Arguments2, true); CLuaArguments Arguments3; Arguments3.PushElement(pVehicle); // vehicle Arguments3.PushNumber(ucSeat); // seat Arguments3.PushElement(pInsidePed); // jacker if (IS_PLAYER(pOutsidePed)) - pOutsidePed->CallEvent("onClientPlayerVehicleExit", Arguments3, true); + pOutsidePed->CallEvent(BuiltInEvents::onClientPlayerVehicleExit, Arguments3, true); else - pOutsidePed->CallEvent("onClientPedVehicleExit", Arguments3, true); + pOutsidePed->CallEvent(BuiltInEvents::onClientPedVehicleExit, Arguments3, true); CLuaArguments Arguments4; Arguments4.PushElement(pVehicle); // vehicle Arguments4.PushNumber(ucSeat); // seat if (IS_PLAYER(pInsidePed)) - pInsidePed->CallEvent("onClientPlayerVehicleEnter", Arguments4, true); + pInsidePed->CallEvent(BuiltInEvents::onClientPlayerVehicleEnter, Arguments4, true); else - pInsidePed->CallEvent("onClientPedVehicleEnter", Arguments4, true); + pInsidePed->CallEvent(BuiltInEvents::onClientPedVehicleEnter, Arguments4, true); } } @@ -2112,7 +2112,7 @@ void CPacketHandler::Packet_VehicleTrailer(NetBitStreamInterface& bitStream) // Call the onClientTrailerAttach CLuaArguments Arguments; Arguments.PushElement(pVehicle); - pTrailer->CallEvent("onClientTrailerAttach", Arguments, true); + pTrailer->CallEvent(BuiltInEvents::onClientTrailerAttach, Arguments, true); } else { @@ -2124,7 +2124,7 @@ void CPacketHandler::Packet_VehicleTrailer(NetBitStreamInterface& bitStream) // Call the onClientTrailerDetach CLuaArguments Arguments; Arguments.PushElement(pVehicle); - pTrailer->CallEvent("onClientTrailerDetach", Arguments, true); + pTrailer->CallEvent(BuiltInEvents::onClientTrailerDetach, Arguments, true); } } else @@ -2610,7 +2610,7 @@ void CPacketHandler::Packet_PlayerNetworkStatus(NetBitStreamInterface& bitStream if (pLocalPlayer) { pLocalPlayer->SetIsInNetworkInterruption(ucType == 0); - pLocalPlayer->CallEvent("onClientPlayerNetworkStatus", Arguments, false); + pLocalPlayer->CallEvent(BuiltInEvents::onClientPlayerNetworkStatus, Arguments, false); } } } @@ -4485,11 +4485,11 @@ void CPacketHandler::Packet_ExplosionSync(NetBitStreamInterface& bitStream) Arguments.PushNumber(Type); if (pCreator) { - bCancelExplosion = !pCreator->CallEvent("onClientExplosion", Arguments, true); + bCancelExplosion = !pCreator->CallEvent(BuiltInEvents::onClientExplosion, Arguments, true); } else { - bCancelExplosion = !g_pClientGame->GetRootEntity()->CallEvent("onClientExplosion", Arguments, false); + bCancelExplosion = !g_pClientGame->GetRootEntity()->CallEvent(BuiltInEvents::onClientExplosion, Arguments, false); } } @@ -4509,7 +4509,7 @@ void CPacketHandler::Packet_ExplosionSync(NetBitStreamInterface& bitStream) // Call onClientVehicleExplode CLuaArguments Arguments; - pExplodingVehicle->CallEvent("onClientVehicleExplode", Arguments, true); + pExplodingVehicle->CallEvent(BuiltInEvents::onClientVehicleExplode, Arguments, true); if (!bCancelExplosion) g_pClientGame->m_pManager->GetExplosionManager()->Create(EXP_TYPE_GRENADE, position.data.vecPosition, pCreator, true, -1.0f, false, @@ -4785,50 +4785,60 @@ void CPacketHandler::Packet_PlayerClothes(NetBitStreamInterface& bitStream) void CPacketHandler::Packet_LuaEvent(NetBitStreamInterface& bitStream) { // Read out the event name length - unsigned short usNameLength; - if (bitStream.ReadCompressed(usNameLength)) + unsigned short length; + if (bitStream.ReadCompressed(length)) { // Error? - if (usNameLength > (MAX_EVENT_NAME_LENGTH - 1)) + if (length > (MAX_EVENT_NAME_LENGTH - 1)) { RaiseFatalError(13); return; } - // Read out the name and the entity id - char* szName = new char[usNameLength + 1]; - ElementID EntityID; - if (bitStream.Read(szName, usNameLength) && bitStream.Read(EntityID)) + std::string eventName; + if (!bitStream.ReadStringCharacters(eventName, length)) + return; + + const auto LogError = [&](auto format) { + // Possible warning: Format string is not a string literal. It is, but the compiler is just stupid to figure it out. + // I wont fuck around trying to disable it, so if it appears, just make this function a macro + g_pClientGame->m_pScriptDebugging->LogError(nullptr, format, eventName.c_str()); + }; + + if (BuiltInEvent::Get(eventName)) // Built-in-events are never remotely triggerable { - // Null-terminate it - szName[usNameLength] = 0; + LogError("Server triggered clientside event %s, but it is not marked as remotely triggerable"); + return; + } + + ElementID entityID; + if (!bitStream.Read(entityID)) + return; - // Read out the arguments aswell - CLuaArguments Arguments(bitStream); + CLuaArguments args(bitStream); - // Grab the event. Does it exist and is it remotly triggerable? - SEvent* pEvent = g_pClientGame->m_Events.Get(szName); - if (pEvent) + if (CClientEntity* pEntity = CElementIDs::GetElement(entityID)) + { + if (const CustomEvent* event = CustomEvent::Get(eventName)) { - if (pEvent->bAllowRemoteTrigger) + if (event->IsRemoteTriggerAllowed()) { - // Grab the element we trigger it on - CClientEntity* pEntity = CElementIDs::GetElement(EntityID); - if (pEntity) - { - pEntity->CallEvent(szName, Arguments, true); - } + pEntity->CallEvent(*event, args, true); } else - g_pClientGame->m_pScriptDebugging->LogError(NULL, "Server triggered clientside event %s, but event is not marked as remotly triggerable", - szName); + { + LogError("Server triggered clientside event %s, but it is not marked as remotely triggerable"); + } } else - g_pClientGame->m_pScriptDebugging->LogError(NULL, "Server triggered clientside event %s, but event is not added clientside", szName); + { + LogError("Server triggered clientside event %s, but it is not added clientside"); + } + } + else + { + dassert(0 && "Server triggered client event with non-existant element"); } - - // Delete event name again - delete[] szName; } } diff --git a/Client/mods/deathmatch/logic/CResource.cpp b/Client/mods/deathmatch/logic/CResource.cpp index 353dfb378f8..5098bcfdc58 100644 --- a/Client/mods/deathmatch/logic/CResource.cpp +++ b/Client/mods/deathmatch/logic/CResource.cpp @@ -323,7 +323,7 @@ void CResource::Load() // Call the Lua "onClientResourceStart" event CLuaArguments Arguments; Arguments.PushResource(this); - m_pResourceEntity->CallEvent("onClientResourceStart", Arguments, true); + m_pResourceEntity->CallEvent(BuiltInEvents::onClientResourceStart, Arguments, true); } else assert(0); @@ -335,7 +335,7 @@ void CResource::Stop() m_bStopping = true; CLuaArguments Arguments; Arguments.PushResource(this); - m_pResourceEntity->CallEvent("onClientResourceStop", Arguments, true); + m_pResourceEntity->CallEvent(BuiltInEvents::onClientResourceStop, Arguments, true); } SString CResource::GetState() diff --git a/Client/mods/deathmatch/logic/CResourceFileDownloadManager.cpp b/Client/mods/deathmatch/logic/CResourceFileDownloadManager.cpp index e459df48b96..bae66ec8326 100644 --- a/Client/mods/deathmatch/logic/CResourceFileDownloadManager.cpp +++ b/Client/mods/deathmatch/logic/CResourceFileDownloadManager.cpp @@ -91,7 +91,7 @@ void CResourceFileDownloadManager::UpdatePendingDownloads() arguments.PushString("queued"); CClientEntity* resourceEntity = pResourceFile->GetResource()->GetResourceEntity(); - resourceEntity->CallEvent("onClientResourceFileDownload", arguments, false); + resourceEntity->CallEvent(BuiltInEvents::onClientResourceFileDownload, arguments, false); } } } @@ -156,7 +156,7 @@ void CResourceFileDownloadManager::DoPulse() arguments.PushNumber(uiDownloadedSizeTotal); arguments.PushNumber(GetTransferBox()->GetDownloadTotalSize()); - g_pClientGame->GetRootEntity()->CallEvent("onClientTransferBoxProgressChange", arguments, false); + g_pClientGame->GetRootEntity()->CallEvent(BuiltInEvents::onClientTransferBoxProgressChange, arguments, false); // Check if completed downloading current group if (m_ActiveFileDownloadList.empty()) @@ -171,7 +171,7 @@ void CResourceFileDownloadManager::DoPulse() CLuaArguments arguments; arguments.PushBoolean(false); - g_pClientGame->GetRootEntity()->CallEvent("onClientTransferBoxVisibilityChange", arguments, false); + g_pClientGame->GetRootEntity()->CallEvent(BuiltInEvents::onClientTransferBoxVisibilityChange, arguments, false); } // Load our newly ready resources @@ -203,7 +203,7 @@ void CResourceFileDownloadManager::AddDownloadSize(int iSize) CLuaArguments arguments; arguments.PushBoolean(true); - g_pClientGame->GetRootEntity()->CallEvent("onClientTransferBoxVisibilityChange", arguments, false); + g_pClientGame->GetRootEntity()->CallEvent(BuiltInEvents::onClientTransferBoxVisibilityChange, arguments, false); } GetTransferBox()->AddToDownloadTotalSize(iSize); @@ -306,7 +306,7 @@ void CResourceFileDownloadManager::DownloadFinished(const SHttpDownloadResult& r arguments.PushString(result.bSuccess ? "finished" : "failed"); CClientEntity* resourceEntity = pResourceFile->GetResource()->GetResourceEntity(); - resourceEntity->CallEvent("onClientResourceFileDownload", arguments, false); + resourceEntity->CallEvent(BuiltInEvents::onClientResourceFileDownload, arguments, false); if (result.bSuccess) { diff --git a/Client/mods/deathmatch/logic/CSingularFileDownload.cpp b/Client/mods/deathmatch/logic/CSingularFileDownload.cpp index 268cdb526a6..0599544f0ba 100644 --- a/Client/mods/deathmatch/logic/CSingularFileDownload.cpp +++ b/Client/mods/deathmatch/logic/CSingularFileDownload.cpp @@ -75,7 +75,7 @@ void CSingularFileDownload::CallFinished(bool bSuccess) Arguments.PushBoolean(false); // or false } - m_pResource->GetResourceEntity()->CallEvent("onClientFileDownloadComplete", Arguments, false); + m_pResource->GetResourceEntity()->CallEvent(BuiltInEvents::onClientFileDownloadComplete, Arguments, false); } SetComplete(); } diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index 477df829fc2..af1380db07d 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -14,7 +14,6 @@ using std::list; static CLuaManager* m_pLuaManager; -static CEvents* m_pEvents; static CCoreInterface* m_pCore; static CGame* m_pGame; static CClientGame* m_pClientGame; @@ -49,11 +48,10 @@ static CClientSoundManager* m_pSoundManager; func; \ pList->Release(); \ } -CStaticFunctionDefinitions::CStaticFunctionDefinitions(CLuaManager* pLuaManager, CEvents* pEvents, CCoreInterface* pCore, CGame* pGame, +CStaticFunctionDefinitions::CStaticFunctionDefinitions(CLuaManager* pLuaManager, CCoreInterface* pCore, CGame* pGame, CClientGame* pClientGame, CClientManager* pManager) { m_pLuaManager = pLuaManager; - m_pEvents = pEvents; m_pCore = pCore; m_pGame = pGame; m_pClientGame = pClientGame; @@ -82,67 +80,6 @@ CStaticFunctionDefinitions::~CStaticFunctionDefinitions() { } -bool CStaticFunctionDefinitions::AddEvent(CLuaMain& LuaMain, const char* szName, bool bAllowRemoteTrigger) -{ - assert(szName); - - // Valid name? - if (szName[0] != '\0') - { - // Add our event to CEvents - return m_pEvents->AddEvent(szName, "", &LuaMain, bAllowRemoteTrigger); - } - - return false; -} - -bool CStaticFunctionDefinitions::AddEventHandler(CLuaMain& LuaMain, const char* szName, CClientEntity& Entity, const CLuaFunctionRef& iLuaFunction, - bool bPropagated, EEventPriorityType eventPriority, float fPriorityMod) -{ - assert(szName); - - // We got an event with that name? - if (m_pEvents->Exists(szName)) - { - // Add the event handler - if (Entity.AddEvent(&LuaMain, szName, iLuaFunction, bPropagated, eventPriority, fPriorityMod)) - return true; - } - - return false; -} - -bool CStaticFunctionDefinitions::RemoveEventHandler(CLuaMain& LuaMain, const char* szName, CClientEntity& Entity, const CLuaFunctionRef& iLuaFunction) -{ - assert(szName); - - // We got an event and handler with that name? - if (m_pEvents->Exists(szName)) - { - // ACHTUNG: CHECK WHETHER THE LUA FUNCTION REF IS CORRECTLY FOUND - if (Entity.DeleteEvent(&LuaMain, szName, iLuaFunction)) - { - return true; - } - } - - return false; -} - -bool CStaticFunctionDefinitions::TriggerEvent(const char* szName, CClientEntity& Entity, const CLuaArguments& Arguments, bool& bWasCancelled) -{ - // There is such event? - if (m_pEvents->Exists(szName)) - { - // Call the event - Entity.CallEvent(szName, Arguments, true); - bWasCancelled = m_pEvents->WasEventCancelled(); - return true; - } - - return false; -} - bool CStaticFunctionDefinitions::TriggerServerEvent(const char* szName, CClientEntity& CallWithEntity, CLuaArguments& Arguments) { assert(szName); @@ -202,17 +139,6 @@ bool CStaticFunctionDefinitions::TriggerLatentServerEvent(const char* szName, CC return false; } -bool CStaticFunctionDefinitions::CancelEvent(bool bCancel) -{ - m_pEvents->CancelEvent(bCancel); - return true; -} - -bool CStaticFunctionDefinitions::WasEventCancelled() -{ - return m_pEvents->WasEventCancelled(); -} - bool CStaticFunctionDefinitions::DownloadFile(CResource* pResource, const char* szFile, CResource* pRequestResource, CChecksum checksum) { SString strHTTPDownloadURLFull("%s/%s/%s", g_pClientGame->GetHTTPURL().c_str(), pResource->GetName(), szFile); @@ -249,7 +175,7 @@ bool CStaticFunctionDefinitions::OutputChatBox(const char* szText, unsigned char Arguments.PushNumber(ucGreen); Arguments.PushNumber(ucBlue); - bool bCancelled = !g_pClientGame->GetRootEntity()->CallEvent("onClientChatMessage", Arguments, false); + bool bCancelled = !g_pClientGame->GetRootEntity()->CallEvent(BuiltInEvents::onClientChatMessage, Arguments, false); if (!bCancelled) { m_pCore->ChatPrintfColor("%s", bColorCoded, ucRed, ucGreen, ucBlue, szText); @@ -1460,7 +1386,7 @@ bool CStaticFunctionDefinitions::SetElementModel(CClientEntity& Entity, unsigned CLuaArguments Arguments; Arguments.PushNumber(usCurrentModel); Arguments.PushNumber(usModel); - Ped.CallEvent("onClientElementModelChange", Arguments, true); + Ped.CallEvent(BuiltInEvents::onClientElementModelChange, Arguments, true); break; } case CCLIENTVEHICLE: @@ -1479,7 +1405,7 @@ bool CStaticFunctionDefinitions::SetElementModel(CClientEntity& Entity, unsigned CLuaArguments Arguments; Arguments.PushNumber(usCurrentModel); Arguments.PushNumber(usModel); - Vehicle.CallEvent("onClientElementModelChange", Arguments, true); + Vehicle.CallEvent(BuiltInEvents::onClientElementModelChange, Arguments, true); break; } case CCLIENTOBJECT: @@ -1499,7 +1425,7 @@ bool CStaticFunctionDefinitions::SetElementModel(CClientEntity& Entity, unsigned CLuaArguments Arguments; Arguments.PushNumber(usCurrentModel); Arguments.PushNumber(usModel); - Object.CallEvent("onClientElementModelChange", Arguments, true); + Object.CallEvent(BuiltInEvents::onClientElementModelChange, Arguments, true); break; } case CCLIENTPROJECTILE: @@ -1518,7 +1444,7 @@ bool CStaticFunctionDefinitions::SetElementModel(CClientEntity& Entity, unsigned CLuaArguments Arguments; Arguments.PushNumber(usCurrentModel); Arguments.PushNumber(usModel); - Projectile.CallEvent("onClientElementModelChange", Arguments, true); + Projectile.CallEvent(BuiltInEvents::onClientElementModelChange, Arguments, true); break; } default: @@ -2063,7 +1989,7 @@ bool CStaticFunctionDefinitions::KillPed(CClientEntity& Entity, CClientEntity* p Arguments.PushBoolean(false); Arguments.PushBoolean(bStealth); - pPed.CallEvent("onClientPedWasted", Arguments, false); + pPed.CallEvent(BuiltInEvents::onClientPedWasted, Arguments, false); pPed.RemoveAllWeapons(); return true; @@ -5006,7 +4932,7 @@ CClientGUIElement* CStaticFunctionDefinitions::GUICreateWindow(CLuaMain& LuaMain pGUIElement->SetParent(LuaMain.GetResource()->GetResourceGUIEntity()); // set events - pGUIElement->SetEvents("onClientGUIClose", "onClientGUIKeyDown"); + pGUIElement->SetEvents("onClientGUIClose", "onClientGUIKeyDown"); // TODO: This event isn't even registered, nor does it exist on Wiki... static_cast(pElement)->SetCloseClickHandler(pGUIElement->GetCallback1()); static_cast(pElement)->SetKeyDownHandler(pGUIElement->GetCallback2()); @@ -5114,7 +5040,7 @@ CClientGUIElement* CStaticFunctionDefinitions::GUICreateButton(CLuaMain& LuaMain pGUIElement->SetParent(pParent ? pParent : LuaMain.GetResource()->GetResourceGUIEntity()); // set events - pGUIElement->SetEvents("onClientGUIClicked"); + pGUIElement->SetEvents("onClientGUIClicked"); // TODO: This event isn't even registered, nor does it exist on Wiki... static_cast(pElement)->SetClickHandler(pGUIElement->GetCallback1()); return pGUIElement; @@ -5164,7 +5090,7 @@ CClientGUIElement* CStaticFunctionDefinitions::GUICreateCheckBox(CLuaMain& LuaMa pGUIElement->SetParent(pParent ? pParent : LuaMain.GetResource()->GetResourceGUIEntity()); // set events - pGUIElement->SetEvents("onClientGUIStateChanged"); + pGUIElement->SetEvents("onClientGUIStateChanged"); // TODO: This event isn't even registered, nor does it exist on Wiki... static_cast(pElement)->SetClickHandler(pGUIElement->GetCallback1()); return pGUIElement; @@ -5182,7 +5108,7 @@ CClientGUIElement* CStaticFunctionDefinitions::GUICreateRadioButton(CLuaMain& Lu pGUIElement->SetParent(pParent ? pParent : LuaMain.GetResource()->GetResourceGUIEntity()); // set events - pGUIElement->SetEvents("onClientGUIStateChanged"); + pGUIElement->SetEvents("onClientGUIStateChanged"); // TODO: This event isn't even registered, nor does it exist on Wiki... static_cast(pElement)->SetClickHandler(pGUIElement->GetCallback1()); return pGUIElement; @@ -5353,7 +5279,7 @@ CClientGUIElement* CStaticFunctionDefinitions::GUICreateComboBox(CLuaMain& LuaMa pGUIElement->SetParent(pParent ? pParent : LuaMain.GetResource()->GetResourceGUIEntity()); // set events - pGUIElement->SetEvents("onClientGUIComboBoxAccepted"); + pGUIElement->SetEvents("onClientGUIComboBoxAccepted"); static_cast(pElement)->SetSelectionHandler(pGUIElement->GetCallback1()); return pGUIElement; @@ -7839,7 +7765,7 @@ bool CStaticFunctionDefinitions::StopSound(CClientSound& Sound) // call onClientSoundStopped CLuaArguments Arguments; Arguments.PushString("destroyed"); // Reason - Sound.CallEvent("onClientSoundStopped", Arguments, false); + Sound.CallEvent(BuiltInEvents::onClientSoundStopped, Arguments, false); g_pClientGame->GetElementDeleter()->Delete(&Sound); return true; } @@ -9763,15 +9689,15 @@ bool CStaticFunctionDefinitions::WarpPedIntoVehicle(CClientPed* pPed, CClientVeh Arguments.PushElement(pVehicle); // vehicle Arguments.PushNumber(uiSeat); // seat if (IS_PLAYER(pPed)) - pPed->CallEvent("onClientPlayerVehicleEnter", Arguments, true); + pPed->CallEvent(BuiltInEvents::onClientPlayerVehicleEnter, Arguments, true); else - pPed->CallEvent("onClientPedVehicleEnter", Arguments, true); + pPed->CallEvent(BuiltInEvents::onClientPedVehicleEnter, Arguments, true); // Call the onClientVehicleEnter event CLuaArguments Arguments2; Arguments2.PushElement(pPed); // player / ped Arguments2.PushNumber(uiSeat); // seat - pVehicle->CallEvent("onClientVehicleEnter", Arguments2, true); + pVehicle->CallEvent(BuiltInEvents::onClientVehicleEnter, Arguments2, true); return true; } @@ -9817,15 +9743,15 @@ bool CStaticFunctionDefinitions::RemovePedFromVehicle(CClientPed* pPed) Arguments.PushNumber(uiSeat); // seat Arguments.PushBoolean(false); // jacker if (IS_PLAYER(pPed)) - pPed->CallEvent("onClientPlayerVehicleExit", Arguments, true); + pPed->CallEvent(BuiltInEvents::onClientPlayerVehicleExit, Arguments, true); else - pPed->CallEvent("onClientPedVehicleExit", Arguments, true); + pPed->CallEvent(BuiltInEvents::onClientPedVehicleExit, Arguments, true); // Call onClientVehicleExit CLuaArguments Arguments2; Arguments2.PushElement(pPed); // player / ped Arguments2.PushNumber(uiSeat); // seat - pVehicle->CallEvent("onClientVehicleExit", Arguments2, true); + pVehicle->CallEvent(BuiltInEvents::onClientVehicleExit, Arguments2, true); return true; } diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h index bc14d97bbc8..0a510af1351 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -19,21 +19,13 @@ class CStaticFunctionDefinitions; class CStaticFunctionDefinitions { public: - CStaticFunctionDefinitions(class CLuaManager* pLuaManager, CEvents* pEvents, CCoreInterface* pCore, CGame* pGame, CClientGame* pClientGame, + CStaticFunctionDefinitions(class CLuaManager* pLuaManager, CCoreInterface* pCore, CGame* pGame, CClientGame* pClientGame, CClientManager* pManager); ~CStaticFunctionDefinitions(); - static bool AddEvent(CLuaMain& LuaMain, const char* szName, bool bAllowRemoteTrigger); - static bool AddEventHandler(CLuaMain& LuaMain, const char* szName, CClientEntity& Entity, const CLuaFunctionRef& iLuaFunction, bool bPropagated, - EEventPriorityType eventPriority, float fPriorityMod); - static bool RemoveEventHandler(CLuaMain& LuaMain, const char* szName, CClientEntity& Entity, const CLuaFunctionRef& iLuaFunction); - static bool TriggerEvent(const char* szName, CClientEntity& Entity, const CLuaArguments& Arguments, bool& bWasCancelled); static bool TriggerServerEvent(const char* szName, CClientEntity& CallWithEntity, CLuaArguments& Arguments); static bool TriggerLatentServerEvent(const char* szName, CClientEntity& CallWithEntity, CLuaArguments& Arguments, int bandwidth, CLuaMain* pLuaMain, ushort usResourceNetId); - static bool CancelEvent(bool bCancel); - static bool WasEventCancelled(); - // Misc funcs static bool DownloadFile(CResource* pResource, const char* szFile, CResource* pRequestResource, CChecksum checksum = CChecksum()); diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.Event.cpp b/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.Event.cpp index 4082baf00ce..dde9e7f5b1d 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.Event.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.Event.cpp @@ -9,134 +9,40 @@ *****************************************************************************/ #include "StdInc.h" +#include // TOOD remove +#include +#include -int CLuaFunctionDefs::AddEvent(lua_State* luaVM) +const Event* ResolveEvent(const std::string& name) { - // bool addEvent ( string eventName [, bool allowRemoteTrigger = false ] ) - SString strName; - bool bAllowRemoteTrigger; - - CScriptArgReader argStream(luaVM); - argStream.ReadString(strName); - argStream.ReadBool(bAllowRemoteTrigger, false); - - if (!argStream.HasErrors()) - { - // Grab our virtual machine - CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); - if (pLuaMain) - { - // Do it - if (CStaticFunctionDefinitions::AddEvent(*pLuaMain, strName, bAllowRemoteTrigger)) - { - lua_pushboolean(luaVM, true); - return 1; - } - } - } - else - m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); - - // Failed - lua_pushboolean(luaVM, false); - return 1; + if (const Event* event = Event::Get(name)) + return event; + throw std::invalid_argument("Event doesn't exist"); } -int CLuaFunctionDefs::AddEventHandler(lua_State* luaVM) +bool CLuaFunctionDefs::RemoveEventHandler(lua_State* L, std::string eventName, CClientEntity* attachedTo, CLuaFunctionRef handlerfn) { - // bool addEventHandler ( string eventName, element attachedTo, function handlerFunction [, bool getPropagated = true, string priority = "normal" ] ) - SString strName; - CClientEntity* pEntity; - CLuaFunctionRef iLuaFunction; - bool bPropagated; - SString strPriority; - - CScriptArgReader argStream(luaVM); - argStream.ReadString(strName); - argStream.ReadUserData(pEntity); - argStream.ReadFunction(iLuaFunction); - argStream.ReadBool(bPropagated, true); - argStream.ReadString(strPriority, "normal"); - argStream.ReadFunctionComplete(); - - // Check if strPriority has a number as well. e.g. name+1 or name-1.32 - float fPriorityMod = 0; - EEventPriorityType eventPriority; - { - uint iPos = strPriority.find_first_of("-+"); - if (iPos != SString::npos) - { - fPriorityMod = (float)atof(strPriority.SubStr(iPos)); - strPriority = strPriority.Left(iPos); - } - - if (!StringToEnum(strPriority, eventPriority)) - argStream.SetTypeError(GetEnumTypeName(eventPriority), 5); // priority is argument #5 - } - - if (!argStream.HasErrors()) - { - // Grab our virtual machine - CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); - if (pLuaMain) - { - // Check if the handle is in use - if (pEntity->GetEventManager()->HandleExists(pLuaMain, strName, iLuaFunction)) - { - argStream.SetCustomError(SString("'%s' with this function is already handled", *strName)); - } - else - { - // Do it - if (CStaticFunctionDefinitions::AddEventHandler(*pLuaMain, strName, *pEntity, iLuaFunction, bPropagated, eventPriority, fPriorityMod)) - { - lua_pushboolean(luaVM, true); - return 1; - } - } - } - } - if (argStream.HasErrors()) - m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); - - // Failed - lua_pushboolean(luaVM, false); - return 1; + return attachedTo->GetEventHandlerCallDispatcher().Remove(*ResolveEvent(eventName), m_pLuaManager->GetVirtualMachine(L), handlerfn); } -int CLuaFunctionDefs::RemoveEventHandler(lua_State* luaVM) +bool CLuaFunctionDefs::AddEventHandler(lua_State* L, std::string eventName, CClientEntity* attachedTo, + CLuaFunctionRef handlerfn, std::optional propagated, std::optional priorityToParse) { - // bool removeEventHandler ( string eventName, element attachedTo, function functionVar ) - SString strName; - CClientEntity* pEntity; - CLuaFunctionRef iLuaFunction; + EventHandler::Priority priority{ priorityToParse.value_or("") }; // Might throw invalid_argument - CScriptArgReader argStream(luaVM); - argStream.ReadString(strName); - argStream.ReadUserData(pEntity); - argStream.ReadFunction(iLuaFunction); - argStream.ReadFunctionComplete(); + const Event* event = ResolveEvent(eventName); + std::cout << "Add event " << eventName << "[Priority: " << priority.ToString() << "]\n"; // TODO Remove - if (!argStream.HasErrors()) - { - // Grab our virtual machine - CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); - if (pLuaMain) - { - // Do it - if (CStaticFunctionDefinitions::RemoveEventHandler(*pLuaMain, strName, *pEntity, iLuaFunction)) - { - lua_pushboolean(luaVM, true); - return 1; - } - } - } - else - m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + return attachedTo->GetEventHandlerCallDispatcher().Add(*event, + { priority, m_pLuaManager->GetVirtualMachine(L), handlerfn, propagated.value_or(true) } + ); +} - // Failed - lua_pushboolean(luaVM, false); - return 1; +bool CLuaFunctionDefs::AddEvent(lua_State* L, std::string name, std::optional allowRemoteTrigger) +{ + if (name.empty()) + return false; // Invalid name (maybe throw here?) + return CustomEvent::Add(name, m_pLuaManager->GetVirtualMachine(L), allowRemoteTrigger.value_or(false)); } int CLuaFunctionDefs::GetEventHandlers(lua_State* luaVM) @@ -151,16 +57,17 @@ int CLuaFunctionDefs::GetEventHandlers(lua_State* luaVM) if (!argStream.HasErrors()) { - // Grab our virtual machine - CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); - if (pLuaMain) + if (CLuaMain* lmain = m_pLuaManager->GetVirtualMachine(luaVM)) { - // Create a new table - lua_newtable(luaVM); - - pElement->GetEventManager()->GetHandles(pLuaMain, (const char*)strName, luaVM); - - return 1; + if (auto* event = Event::Get(strName)) + { + if (auto* handlers = pElement->GetEventHandlerCallDispatcher().GetHandlers(*event)) + { + lua_newtable(luaVM); + handlers->PushToLua(lmain, luaVM); + return 1; + } + } } } else @@ -174,29 +81,26 @@ int CLuaFunctionDefs::GetEventHandlers(lua_State* luaVM) int CLuaFunctionDefs::TriggerEvent(lua_State* luaVM) { // bool triggerEvent ( string eventName, element baseElement, [ var argument1, ... ] ) - SString strName; - CClientEntity* pEntity; - CLuaArguments Arguments; + SString strName; + CElement* pElement; + CLuaArguments Arguments; CScriptArgReader argStream(luaVM); argStream.ReadString(strName); - argStream.ReadUserData(pEntity); + argStream.ReadUserData(pElement); argStream.ReadLuaArguments(Arguments); if (!argStream.HasErrors()) { - // Trigger it - bool bWasCancelled; - if (CStaticFunctionDefinitions::TriggerEvent(strName, *pEntity, Arguments, bWasCancelled)) + if (auto* event = Event::Get(strName)) { - lua_pushboolean(luaVM, !bWasCancelled); + lua_pushboolean(luaVM, !pElement->CallEvent(*event, Arguments)); return 1; } } else m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); - // Error lua_pushnil(luaVM); return 1; } @@ -267,25 +171,15 @@ int CLuaFunctionDefs::TriggerServerEvent(lua_State* luaVM) return 1; } -int CLuaFunctionDefs::CancelEvent(lua_State* luaVM) +bool CLuaFunctionDefs::CancelEvent() { - // Cancel it - if (CStaticFunctionDefinitions::CancelEvent(true)) - { - lua_pushboolean(luaVM, true); - return 1; - } - - // Failed - lua_pushboolean(luaVM, false); - return 1; + s_EventDispatcher.CancelEvent(true, ""); + return true; } -int CLuaFunctionDefs::WasEventCancelled(lua_State* luaVM) +bool CLuaFunctionDefs::WasEventCancelled() { - // Return whether the last event was cancelled or not - lua_pushboolean(luaVM, CStaticFunctionDefinitions::WasEventCancelled()); - return 1; + return s_EventDispatcher.WasEventCancelled(); } int CLuaFunctionDefs::TriggerLatentServerEvent(lua_State* luaVM) diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.h b/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.h index 73ed0137390..2ea703be6b4 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.h +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionDefs.h @@ -28,14 +28,15 @@ class CLuaFunctionDefs static void Initialize(class CLuaManager* pLuaManager, class CScriptDebugging* pScriptDebugging, class CClientGame* pClientGame); // Event functions - LUA_DECLARE(AddEvent); - LUA_DECLARE(AddEventHandler); - LUA_DECLARE(RemoveEventHandler); + static bool RemoveEventHandler(lua_State* L, std::string eventName, CClientEntity* attachedTo, CLuaFunctionRef handlerfn); + static bool AddEventHandler(lua_State* L, std::string eventName, CClientEntity* attachedTo, + CLuaFunctionRef handlerfn, std::optional propagated, std::optional priorityToParse); + static bool AddEvent(lua_State* L, std::string name, std::optional allowRemoteTrigger); + static bool CancelEvent(); + static bool WasEventCancelled(); LUA_DECLARE(GetEventHandlers); LUA_DECLARE(TriggerEvent); LUA_DECLARE(TriggerServerEvent); - LUA_DECLARE(CancelEvent); - LUA_DECLARE(WasEventCancelled); LUA_DECLARE(TriggerLatentServerEvent); LUA_DECLARE(GetLatentEventHandles); LUA_DECLARE(GetLatentEventStatus); diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionRef.h b/Client/mods/deathmatch/logic/lua/CLuaFunctionRef.h index 1ce043a2501..e32421645dc 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionRef.h +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionRef.h @@ -15,6 +15,8 @@ #define VERIFY_FUNCTION(func) ( (func).ToInt () != LUA_REFNIL ) #define IS_REFNIL(func) ( (func).ToInt () == LUA_REFNIL ) +struct lua_State; + class CLuaFunctionRef { public: diff --git a/Client/mods/deathmatch/logic/lua/CLuaMain.cpp b/Client/mods/deathmatch/logic/lua/CLuaMain.cpp index 4f97dc44ba4..3a3580cfb57 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaMain.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaMain.cpp @@ -26,6 +26,7 @@ SString CLuaMain::ms_strExpectedUndumpHash; #include "luascripts/coroutine_debug.lua.h" #include "luascripts/exports.lua.h" #include "luascripts/inspect.lua.h" +#include "luascripts/DispatchEvent.lua.h" CLuaMain::CLuaMain(CLuaManager* pLuaManager, CResource* pResourceOwner, bool bEnableOOP) { @@ -188,6 +189,19 @@ void CLuaMain::InitVM() LoadScript(EmbeddedLuaCode::exports); LoadScript(EmbeddedLuaCode::coroutine_debug); LoadScript(EmbeddedLuaCode::inspect); + { + LoadScript(EmbeddedLuaCode::DispatchEvent); + + lua_getglobal(m_luaVM, "DispatchEvent"); + //const auto ptr = lua_topointer(m_luaVM, -1); + //const int ref = lua_ref(m_luaVM, true); // it pops the value + //m_fnDispatchEvent = { m_luaVM, ref, ptr }; + m_fnrefDispatchEvent = lua_ref(m_luaVM, true); + dassert(m_fnrefDispatchEvent != LUA_REFNIL); + + lua_pushnil(m_luaVM); + lua_setglobal(m_luaVM, "DispatchEvent"); // nil function out, so it doesn't conflit with people's code + } DECLARE_PROFILER_SECTION(OnPostLoadScript) } diff --git a/Client/mods/deathmatch/logic/lua/CLuaMain.h b/Client/mods/deathmatch/logic/lua/CLuaMain.h index 778564ddbeb..5c7eb6552b6 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaMain.h +++ b/Client/mods/deathmatch/logic/lua/CLuaMain.h @@ -79,6 +79,7 @@ class CLuaMain //: public CClient bool IsOOPEnabled() { return m_bEnableOOP; } + int GetDispatchEventFnRef() const { return m_fnrefDispatchEvent; } private: void InitSecurity(); @@ -101,6 +102,10 @@ class CLuaMain //: public CClient bool m_bEnableOOP; + + // Ref to special event handler function from internal script in InitVM() + // Code: "luascripts/DispatchEvent.lua.h" + int m_fnrefDispatchEvent; public: CFastHashMap m_CallbackTable; std::map m_FunctionTagMap; diff --git a/Client/mods/deathmatch/logic/lua/CLuaManager.cpp b/Client/mods/deathmatch/logic/lua/CLuaManager.cpp index 0f41e7396e7..121f66dedbb 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaManager.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaManager.cpp @@ -12,6 +12,8 @@ #include "StdInc.h" #include "../luadefs/CLuaFireDefs.h" #include "../luadefs/CLuaClientDefs.h" +#include +#include using std::list; @@ -23,7 +25,6 @@ static int DummyPreCall(lua_CFunction f, lua_State* L) CLuaManager::CLuaManager(CClientGame* pClientGame) { - m_pEvents = pClientGame->GetEvents(); m_pGUIManager = pClientGame->GetGUIManager(); m_pRegisteredCommands = pClientGame->GetRegisteredCommands(); @@ -69,7 +70,7 @@ bool CLuaManager::RemoveVirtualMachine(CLuaMain* pLuaMain) if (pLuaMain) { // Remove all events registered by it - m_pEvents->RemoveAllEvents(pLuaMain); + s_CustomEvents.RemoveAllOf(pLuaMain); m_pRegisteredCommands->CleanUpForVM(pLuaMain); // Remove it from our list @@ -154,14 +155,14 @@ void CLuaManager::LoadCFunctions() { constexpr static const std::pair functions[]{ // Event funcs - {"addEvent", CLuaFunctionDefs::AddEvent}, - {"addEventHandler", CLuaFunctionDefs::AddEventHandler}, - {"removeEventHandler", CLuaFunctionDefs::RemoveEventHandler}, + {"addEvent", CLuaDefs::ArgumentParserWarn}, + {"addEventHandler", CLuaDefs::ArgumentParserWarn}, + {"removeEventHandler", CLuaDefs::ArgumentParserWarn}, + {"cancelEvent", CLuaDefs::ArgumentParserWarn}, + {"wasEventCancelled", CLuaDefs::ArgumentParserWarn}, {"getEventHandlers", CLuaFunctionDefs::GetEventHandlers}, {"triggerEvent", CLuaFunctionDefs::TriggerEvent}, {"triggerServerEvent", CLuaFunctionDefs::TriggerServerEvent}, - {"cancelEvent", CLuaFunctionDefs::CancelEvent}, - {"wasEventCancelled", CLuaFunctionDefs::WasEventCancelled}, {"triggerLatentServerEvent", CLuaFunctionDefs::TriggerLatentServerEvent}, {"getLatentEventHandles", CLuaFunctionDefs::GetLatentEventHandles}, {"getLatentEventStatus", CLuaFunctionDefs::GetLatentEventStatus}, diff --git a/Client/mods/deathmatch/logic/lua/CLuaManager.h b/Client/mods/deathmatch/logic/lua/CLuaManager.h index 4cf637f5cd7..7fc10630438 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaManager.h +++ b/Client/mods/deathmatch/logic/lua/CLuaManager.h @@ -16,7 +16,6 @@ class CLuaManager; #include #include "../CClientGUIManager.h" -#include "../CEvents.h" #include "../CScriptDebugging.h" #include "CLuaMain.h" #include "../CRegisteredCommands.h" @@ -48,7 +47,6 @@ class CLuaManager private: void LoadCFunctions(); - CEvents* m_pEvents; CRegisteredCommands* m_pRegisteredCommands; CFastHashMap m_VirtualMachineMap; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaAudioDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaAudioDefs.cpp index 9e1c5c4312e..81872efa3b6 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaAudioDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaAudioDefs.cpp @@ -183,7 +183,7 @@ int CLuaAudioDefs::PlaySound(lua_State* luaVM) // call onClientSoundStarted CLuaArguments Arguments; Arguments.PushString("play"); // Reason - pSound->CallEvent("onClientSoundStarted", Arguments, false); + pSound->CallEvent(BuiltInEvents::onClientSoundStarted, Arguments, false); lua_pushelement(luaVM, pSound); return 1; @@ -243,7 +243,7 @@ int CLuaAudioDefs::PlaySound3D(lua_State* luaVM) // call onClientSoundStarted CLuaArguments Arguments; Arguments.PushString("play"); // Reason - pSound->CallEvent("onClientSoundStarted", Arguments, false); + pSound->CallEvent(BuiltInEvents::onClientSoundStarted, Arguments, false); lua_pushelement(luaVM, pSound); return 1; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaDefs.h index 5d206c11823..bd80c355870 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaDefs.h @@ -65,7 +65,7 @@ class CLuaDefs static CClientColModelManager* m_pColModelManager; static CRegisteredCommands* m_pRegisteredCommands; -protected: + // Old style: Only warn on failure. This should // not be used for new functions. ReturnOnError // must be a value to use as result on invalid argument diff --git a/Client/mods/deathmatch/logic/rpc/CElementRPCs.cpp b/Client/mods/deathmatch/logic/rpc/CElementRPCs.cpp index 179b04f890e..7db6349df7f 100644 --- a/Client/mods/deathmatch/logic/rpc/CElementRPCs.cpp +++ b/Client/mods/deathmatch/logic/rpc/CElementRPCs.cpp @@ -455,7 +455,7 @@ void CElementRPCs::SetElementModel(CClientEntity* pSource, NetBitStreamInterface CLuaArguments Arguments; Arguments.PushNumber(usCurrentModel); Arguments.PushNumber(usModel); - pPed->CallEvent("onClientElementModelChange", Arguments, true); + pPed->CallEvent(BuiltInEvents::onClientElementModelChange, Arguments, true); } } @@ -481,7 +481,7 @@ void CElementRPCs::SetElementModel(CClientEntity* pSource, NetBitStreamInterface CLuaArguments Arguments; Arguments.PushNumber(usCurrentModel); Arguments.PushNumber(usModel); - pVehicle->CallEvent("onClientElementModelChange", Arguments, true); + pVehicle->CallEvent(BuiltInEvents::onClientElementModelChange, Arguments, true); } break; @@ -499,7 +499,7 @@ void CElementRPCs::SetElementModel(CClientEntity* pSource, NetBitStreamInterface CLuaArguments Arguments; Arguments.PushNumber(usCurrentModel); Arguments.PushNumber(usModel); - pObject->CallEvent("onClientElementModelChange", Arguments, true); + pObject->CallEvent(BuiltInEvents::onClientElementModelChange, Arguments, true); } break; diff --git a/Server/mods/deathmatch/StdInc.h b/Server/mods/deathmatch/StdInc.h index 4fe445cd8c7..38d25a88b84 100644 --- a/Server/mods/deathmatch/StdInc.h +++ b/Server/mods/deathmatch/StdInc.h @@ -217,7 +217,6 @@ struct SAclRequest; #include "CElementGroup.h" #include "CElementIDs.h" #include "CElementRefManager.h" -#include "CEvents.h" #include "CGame.h" #include "CGroups.h" #include "CHTTPD.h" @@ -228,8 +227,6 @@ struct SAclRequest; #include "CLightsyncManager.h" #include "CLogger.h" #include "CMainConfig.h" -#include "CMapEvent.h" -#include "CMapEventManager.h" #include "CMapManager.h" #include "CMarker.h" #include "CMarkerManager.h" diff --git a/Server/mods/deathmatch/logic/CAccountManager.cpp b/Server/mods/deathmatch/logic/CAccountManager.cpp index 101b9d66281..ebf85816c02 100644 --- a/Server/mods/deathmatch/logic/CAccountManager.cpp +++ b/Server/mods/deathmatch/logic/CAccountManager.cpp @@ -583,7 +583,7 @@ bool CAccountManager::LogIn(CClient* pClient, CClient* pEchoClient, const std::s Arguments.PushAccount(pCurrentAccount); Arguments.PushAccount(pAccount); Arguments.PushBoolean(false); // was bAutoLogin - if (!pPlayer->CallEvent("onPlayerLogin", Arguments)) + if (!pPlayer->CallEvent(BuiltInEvents::onPlayerLogin, Arguments)) { // DENIED! pClient->SetAccount(pCurrentAccount); @@ -640,7 +640,7 @@ bool CAccountManager::LogOut(CClient* pClient, CClient* pEchoClient) CLuaArguments Arguments; Arguments.PushAccount(pCurrentAccount); Arguments.PushAccount(pAccount); - if (!pPlayer->CallEvent("onPlayerLogout", Arguments)) + if (!pPlayer->CallEvent(BuiltInEvents::onPlayerLogout, Arguments)) { // DENIED! pClient->SetAccount(pCurrentAccount); diff --git a/Server/mods/deathmatch/logic/CBanManager.cpp b/Server/mods/deathmatch/logic/CBanManager.cpp index 369378daea6..aee4bae2e90 100644 --- a/Server/mods/deathmatch/logic/CBanManager.cpp +++ b/Server/mods/deathmatch/logic/CBanManager.cpp @@ -53,7 +53,7 @@ void CBanManager::DoPulse() // Trigger the event CLuaArguments Arguments; Arguments.PushBan(*iter); - g_pGame->GetMapManager()->GetRootElement()->CallEvent("onUnban", Arguments); + g_pGame->GetMapManager()->GetRootElement()->CallEvent(BuiltInEvents::onUnban, Arguments); RemoveBan(*iter); iter = m_BanManager.begin(); diff --git a/Server/mods/deathmatch/logic/CBlipManager.cpp b/Server/mods/deathmatch/logic/CBlipManager.cpp index 21e1ed08326..9a410c61a51 100644 --- a/Server/mods/deathmatch/logic/CBlipManager.cpp +++ b/Server/mods/deathmatch/logic/CBlipManager.cpp @@ -28,11 +28,11 @@ CBlip* CBlipManager::Create(CElement* pParent) return pBlip; } -CBlip* CBlipManager::CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents) +CBlip* CBlipManager::CreateFromXML(CElement* pParent, CXMLNode& Node) { CBlip* const pBlip = new CBlip(pParent, this); - if (pBlip->GetID() == INVALID_ELEMENT_ID || !pBlip->LoadFromCustomData(pEvents, Node)) + if (pBlip->GetID() == INVALID_ELEMENT_ID || !pBlip->LoadFromCustomData(Node)) { delete pBlip; return nullptr; diff --git a/Server/mods/deathmatch/logic/CBlipManager.h b/Server/mods/deathmatch/logic/CBlipManager.h index fe8b8e71b99..767d25d8ae5 100644 --- a/Server/mods/deathmatch/logic/CBlipManager.h +++ b/Server/mods/deathmatch/logic/CBlipManager.h @@ -25,7 +25,7 @@ class CBlipManager ~CBlipManager() { DeleteAll(); }; CBlip* Create(CElement* pParent); - CBlip* CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents); + CBlip* CreateFromXML(CElement* pParent, CXMLNode& Node); void DeleteAll(); unsigned int Count() { return static_cast(m_List.size()); }; diff --git a/Server/mods/deathmatch/logic/CColManager.cpp b/Server/mods/deathmatch/logic/CColManager.cpp index 2bd803361cb..bc70b972dbc 100644 --- a/Server/mods/deathmatch/logic/CColManager.cpp +++ b/Server/mods/deathmatch/logic/CColManager.cpp @@ -141,12 +141,12 @@ void CColManager::HandleHitDetectionResult(bool bHit, CColShape* pShape, CElemen CLuaArguments Arguments; Arguments.PushElement(pEntity); Arguments.PushBoolean((pShape->GetDimension() == pEntity->GetDimension())); - pShape->CallEvent("onColShapeHit", Arguments); + pShape->CallEvent(BuiltInEvents::onColShapeHit, Arguments); CLuaArguments Arguments2; Arguments2.PushElement(pShape); Arguments2.PushBoolean((pShape->GetDimension() == pEntity->GetDimension())); - pEntity->CallEvent("onElementColShapeHit", Arguments2); + pEntity->CallEvent(BuiltInEvents::onElementColShapeHit, Arguments2); } // Run whatever callback the collision item might have attached @@ -166,12 +166,12 @@ void CColManager::HandleHitDetectionResult(bool bHit, CColShape* pShape, CElemen CLuaArguments Arguments; Arguments.PushElement(pEntity); Arguments.PushBoolean((pShape->GetDimension() == pEntity->GetDimension())); - pShape->CallEvent("onColShapeLeave", Arguments); + pShape->CallEvent(BuiltInEvents::onColShapeLeave, Arguments); CLuaArguments Arguments2; Arguments2.PushElement(pShape); Arguments2.PushBoolean((pShape->GetDimension() == pEntity->GetDimension())); - pEntity->CallEvent("onElementColShapeLeave", Arguments2); + pEntity->CallEvent(BuiltInEvents::onElementColShapeLeave, Arguments2); pShape->CallLeaveCallback(*pEntity); } diff --git a/Server/mods/deathmatch/logic/CConsole.cpp b/Server/mods/deathmatch/logic/CConsole.cpp index e05a694504d..52be531f100 100644 --- a/Server/mods/deathmatch/logic/CConsole.cpp +++ b/Server/mods/deathmatch/logic/CConsole.cpp @@ -50,7 +50,7 @@ bool CConsole::HandleInput(const char* szCommand, CClient* pClient, CClient* pEc CLuaArguments Arguments; Arguments.PushString(szKey); - if (!pPlayer->CallEvent("onPlayerCommand", Arguments)) + if (!pPlayer->CallEvent(BuiltInEvents::onPlayerCommand, Arguments)) return false; } @@ -93,7 +93,7 @@ bool CConsole::HandleInput(const char* szCommand, CClient* pClient, CClient* pEc // Call the console event CLuaArguments Arguments; Arguments.PushString(szCommand); - pPlayer->CallEvent("onConsole", Arguments); + pPlayer->CallEvent(BuiltInEvents::onConsole, Arguments); } break; } @@ -106,7 +106,7 @@ bool CConsole::HandleInput(const char* szCommand, CClient* pClient, CClient* pEc // Call the console event CLuaArguments Arguments; Arguments.PushString(szCommand); - pConsole->CallEvent("onConsole", Arguments); + pConsole->CallEvent(BuiltInEvents::onConsole, Arguments); break; } default: diff --git a/Server/mods/deathmatch/logic/CConsoleCommands.cpp b/Server/mods/deathmatch/logic/CConsoleCommands.cpp index ed4d8e980c9..26963ec6915 100644 --- a/Server/mods/deathmatch/logic/CConsoleCommands.cpp +++ b/Server/mods/deathmatch/logic/CConsoleCommands.cpp @@ -341,7 +341,7 @@ bool CConsoleCommands::Say(CConsole* pConsole, const char* szInArguments, CClien CLuaArguments Arguments; Arguments.PushString(szArguments); Arguments.PushNumber(0); // Normal chat - bool bContinue = static_cast(pClient)->CallEvent("onPlayerChat", Arguments); + bool bContinue = static_cast(pClient)->CallEvent(BuiltInEvents::onPlayerChat, Arguments); if (bContinue) { // Log it in the console @@ -364,7 +364,7 @@ bool CConsoleCommands::Say(CConsole* pConsole, const char* szInArguments, CClien CLuaArguments Arguments2; Arguments2.PushString(szArguments); Arguments2.PushElement(pPlayer); - pPlayer->CallEvent("onChatMessage", Arguments2); + pPlayer->CallEvent(BuiltInEvents::onChatMessage, Arguments2); } break; @@ -476,7 +476,7 @@ bool CConsoleCommands::TeamSay(CConsole* pConsole, const char* szInArguments, CC CLuaArguments Arguments; Arguments.PushString(szArguments); Arguments.PushNumber(2); // Team chat - bool bContinue = static_cast(pClient)->CallEvent("onPlayerChat", Arguments); + bool bContinue = static_cast(pClient)->CallEvent(BuiltInEvents::onPlayerChat, Arguments); if (bContinue) { // Log it in the console @@ -494,7 +494,7 @@ bool CConsoleCommands::TeamSay(CConsole* pConsole, const char* szInArguments, CC CLuaArguments Arguments2; Arguments2.PushString(szArguments); Arguments2.PushElement(pTeam); - static_cast(pClient)->CallEvent("onChatMessage", Arguments2); + static_cast(pClient)->CallEvent(BuiltInEvents::onChatMessage, Arguments2); } // Success @@ -584,7 +584,7 @@ bool CConsoleCommands::Msg(CConsole* pConsole, const char* szInArguments, CClien CLuaArguments Arguments; Arguments.PushString(szArguments); Arguments.PushElement(pPlayer); - bool bContinue = pSender->CallEvent("onPlayerPrivateMessage", Arguments); + bool bContinue = pSender->CallEvent(BuiltInEvents::onPlayerPrivateMessage, Arguments); if (bContinue) { // Send it to the player @@ -682,7 +682,7 @@ bool CConsoleCommands::Me(CConsole* pConsole, const char* szArguments, CClient* CLuaArguments Arguments; Arguments.PushString(szArguments); // text Arguments.PushNumber(1); // Me chat - bool bContinue = static_cast(pClient)->CallEvent("onPlayerChat", Arguments); + bool bContinue = static_cast(pClient)->CallEvent(BuiltInEvents::onPlayerChat, Arguments); if (bContinue) { // Log it in the console @@ -696,7 +696,7 @@ bool CConsoleCommands::Me(CConsole* pConsole, const char* szArguments, CClient* CLuaArguments Arguments2; Arguments2.PushString(szArguments); Arguments2.PushElement(pPlayer); - static_cast(pClient)->CallEvent("onChatMessage", Arguments2); + static_cast(pClient)->CallEvent(BuiltInEvents::onChatMessage, Arguments2); } } @@ -751,7 +751,7 @@ bool CConsoleCommands::Nick(CConsole* pConsole, const char* szArguments, CClient Arguments.PushString(pClient->GetNick()); Arguments.PushString(szNewNick); Arguments.PushBoolean(true); // manually changed - if (pPlayer->CallEvent("onPlayerChangeNick", Arguments)) + if (pPlayer->CallEvent(BuiltInEvents::onPlayerChangeNick, Arguments)) { // Tell the console CLogger::LogPrintf("NICK: %s is now known as %s\n", szNick, szNewNick); diff --git a/Server/mods/deathmatch/logic/CElement.cpp b/Server/mods/deathmatch/logic/CElement.cpp index 9ba24b51c12..a70cb832ae3 100644 --- a/Server/mods/deathmatch/logic/CElement.cpp +++ b/Server/mods/deathmatch/logic/CElement.cpp @@ -10,7 +10,8 @@ *****************************************************************************/ #include "StdInc.h" - +#include +#include extern CGame* g_pGame; #if defined(_MSC_VER) @@ -50,7 +51,6 @@ CElement::CElement(CElement* pParent) CElement::AddEntityFromRoot(m_uiTypeHash, this); // Make an event manager for us - m_pEventManager = new CMapEventManager; m_pCustomData = new CCustomData; m_pAttachedTo = NULL; @@ -68,7 +68,6 @@ CElement::~CElement() // Delete our event manager delete m_pCustomData; - delete m_pEventManager; // Unreference us from what's referencing us list::const_iterator iter = m_ElementReferenced.begin(); @@ -414,46 +413,16 @@ CElement* CElement::SetParentObject(CElement* pParent, bool bUpdatePerPlayerEnti return pParent; } -bool CElement::AddEvent(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction, bool bPropagated, EEventPriorityType eventPriority, - float fPriorityMod) +bool CElement::CallEvent(const Event& event, const CLuaArguments& Arguments, CPlayer* pCaller) { - return m_pEventManager->Add(pLuaMain, szName, iLuaFunction, bPropagated, eventPriority, fPriorityMod); -} - -bool CElement::CallEvent(const char* szName, const CLuaArguments& Arguments, CPlayer* pCaller) -{ - if (!g_pGame->GetDebugHookManager()->OnPreEvent(szName, Arguments, this, pCaller)) - return false; - - CEvents* pEvents = g_pGame->GetEvents(); - - // Make sure our event-manager knows we're about to call an event - pEvents->PreEventPulse(); - - // Call the event on our parents/us first - CallParentEvent(szName, Arguments, this, pCaller); - - // Call it on all our children - CallEventNoParent(szName, Arguments, this, pCaller); - - // Tell the event manager that we're done calling the event - pEvents->PostEventPulse(); - - g_pGame->GetDebugHookManager()->OnPostEvent(szName, Arguments, this, pCaller); - // Return whether our event was cancelled or not - return (!pEvents->WasEventCancelled()); -} - -bool CElement::DeleteEvent(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction) -{ - return m_pEventManager->Delete(pLuaMain, szName, iLuaFunction); + return s_EventDispatcher.Call(event, Arguments, true, this, pCaller); } void CElement::DeleteEvents(CLuaMain* pLuaMain, bool bRecursive) { // Delete it from our events - m_pEventManager->Delete(pLuaMain); + GetEventHandlerCallDispatcher().Remove(pLuaMain); // Delete it from all our children's events if (bRecursive) @@ -468,13 +437,11 @@ void CElement::DeleteEvents(CLuaMain* pLuaMain, bool bRecursive) void CElement::DeleteAllEvents() { - m_pEventManager->DeleteAll(); + GetEventHandlerCallDispatcher().Clear(); } -void CElement::ReadCustomData(CEvents* pEvents, CXMLNode& Node) +void CElement::ReadCustomData(CXMLNode& Node) { - assert(pEvents); - // Iterate the attributes of our XML node CXMLAttributes* pAttributes = &(Node.GetAttributes()); unsigned int uiAttributeCount = pAttributes->Count(); @@ -720,7 +687,8 @@ void CElement::SetCustomData(const char* szName, const CLuaArgument& Variable, E Arguments.PushString(szName); Arguments.PushArgument(oldVariable); Arguments.PushArgument(Variable); - CallEvent("onElementDataChange", Arguments, pClient); + CallEvent(BuiltInEvents::onElementDataChange, Arguments, pClient); + //CallEvent("onElementDataChange", Arguments, pClient); } } @@ -741,7 +709,7 @@ void CElement::DeleteCustomData(const char* szName) Arguments.PushString(szName); Arguments.PushArgument(oldVariable); Arguments.PushArgument(CLuaArgument()); // Use nil as the new value to indicate the data has been removed - CallEvent("onElementDataChange", Arguments); + CallEvent(BuiltInEvents::onElementDataChange, Arguments); } } @@ -791,7 +759,6 @@ void CElement::CleanUpForVM(CLuaMain* pLuaMain, bool bRecursive) // Delete all our events and custom datas attached to that VM DeleteEvents(pLuaMain, false); // DeleteCustomData ( pLuaMain, false ); * Removed to keep custom data global - // If recursive, do it on our children too if (bRecursive) { @@ -803,12 +770,10 @@ void CElement::CleanUpForVM(CLuaMain* pLuaMain, bool bRecursive) } } -bool CElement::LoadFromCustomData(CEvents* pEvents, CXMLNode& Node) +bool CElement::LoadFromCustomData(CXMLNode& Node) { - assert(pEvents); - // Read out all the attributes into our custom data records - ReadCustomData(pEvents, Node); + ReadCustomData(Node); // Grab the "id" custom data into our m_strName member char szBuf[MAX_ELEMENT_NAME_LENGTH + 1] = {0}; @@ -993,48 +958,6 @@ void CElement::FindAllChildrenByTypeIndex(unsigned int uiTypeHash, lua_State* pL } } -void CElement::CallEventNoParent(const char* szName, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller) -{ - // Call it on us if this isn't the same class it was raised on - if (pSource != this && m_pEventManager->HasEvents()) - { - m_pEventManager->Call(szName, Arguments, pSource, this, pCaller); - } - - // Call it on all our children - CElementListSnapshot* pList = GetChildrenListSnapshot(); - pList->AddRef(); // Keep list alive during use - for (CElementListSnapshot::const_iterator iter = pList->begin(); iter != pList->end(); iter++) - { - CElement* pElement = *iter; - if (!pElement->IsBeingDeleted()) - { - if (!pElement->m_pEventManager || pElement->m_pEventManager->HasEvents() || !pElement->m_Children.empty()) - { - pElement->CallEventNoParent(szName, Arguments, pSource, pCaller); - if (m_bIsBeingDeleted) - break; - } - } - } - pList->Release(); -} - -void CElement::CallParentEvent(const char* szName, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller) -{ - // Call the event on us - if (m_pEventManager->HasEvents()) - { - m_pEventManager->Call(szName, Arguments, pSource, this, pCaller); - } - - // Call parent's handler - if (m_pParent) - { - m_pParent->CallParentEvent(szName, Arguments, pSource, pCaller); - } -} - bool CElement::CollisionExists(CColShape* pShape) { list::iterator iter = m_Collisions.begin(); @@ -1069,7 +992,7 @@ void CElement::SetDimension(unsigned short usDimension) CLuaArguments Arguments; Arguments.PushNumber(usOldDimension); Arguments.PushNumber(usDimension); - CallEvent("onElementDimensionChange", Arguments); + CallEvent(BuiltInEvents::onElementDimensionChange, Arguments); } void CElement::SetInterior(unsigned char ucInterior) @@ -1083,7 +1006,7 @@ void CElement::SetInterior(unsigned char ucInterior) CLuaArguments Arguments; Arguments.PushNumber(ucOldInterior); Arguments.PushNumber(ucInterior); - CallEvent("onElementInteriorChange", Arguments); + CallEvent(BuiltInEvents::onElementInteriorChange, Arguments); } CClient* CElement::GetClient() diff --git a/Server/mods/deathmatch/logic/CElement.h b/Server/mods/deathmatch/logic/CElement.h index d7a3e070828..f143be58475 100644 --- a/Server/mods/deathmatch/logic/CElement.h +++ b/Server/mods/deathmatch/logic/CElement.h @@ -11,15 +11,17 @@ #pragma once +#include +#include +#include #include #include -#include "CMapEventManager.h" #include "CCustomData.h" -#include "CEvents.h" +#include "CElementGroup.h" #include #include -#include "CElementGroup.h" - +#include +#include // Used to check fast version of getElementsByType //#define CHECK_ENTITIES_FROM_ROOT MTA_DEBUG @@ -87,7 +89,7 @@ class CElement CElement(CElement* pParent); virtual ~CElement(); - virtual CElement* Clone(bool* bAddEntity, CResource* pResource) { return nullptr; } + virtual CElement* Clone(bool* bAddEntity, class CResource* pResource) { return nullptr; } bool IsCloneable(); bool IsBeingDeleted() { return m_bIsBeingDeleted; }; @@ -121,19 +123,16 @@ class CElement GetDescendantsByType((std::vector&)outResult, elementType); } - CMapEventManager* GetEventManager() { return m_pEventManager; }; CElement* GetParentEntity() { return m_pParent; }; CElement* SetParentObject(CElement* pParent, bool bUpdatePerPlayerEntities = true); - bool AddEvent(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction, bool bPropagated, EEventPriorityType eventPriority, - float fPriorityMod); - bool CallEvent(const char* szName, const CLuaArguments& Arguments, CPlayer* pCaller = NULL); + bool CallEvent(const Event& event, const CLuaArguments& Arguments, CPlayer* pCaller = NULL); bool DeleteEvent(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction = CLuaFunctionRef()); void DeleteEvents(CLuaMain* pLuaMain, bool bRecursive); void DeleteAllEvents(); - void ReadCustomData(CEvents* pEvents, CXMLNode& Node); + void ReadCustomData(CXMLNode& Node); CCustomData* GetCustomDataPointer() { return m_pCustomData; } CLuaArgument* GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType = NULL); CLuaArguments* GetAllCustomData(CLuaArguments* table); @@ -166,7 +165,7 @@ class CElement const std::string& GetName() { return m_strName; }; void SetName(const std::string& strName) { m_strName = strName; }; - bool LoadFromCustomData(CEvents* pEvents, CXMLNode& Node); + bool LoadFromCustomData(CXMLNode& Node); void OnSubtreeAdd(CElement* pElement); void OnSubtreeRemove(CElement* pElement); @@ -205,6 +204,7 @@ class CElement CElementGroup* GetElementGroup() { return m_pElementGroup; } void SetElementGroup(CElementGroup* elementGroup) { m_pElementGroup = elementGroup; } + // This is used for realtime synced elements. Whenever a position/rotation change is // forced from the server either in form of spawn or setElementPosition/rotation a new // value is assigned to this from the server. This value also comes with the sync packets. @@ -234,6 +234,57 @@ class CElement bool CanBeDestroyedByScript() { return m_canBeDestroyedByScript; } void SetCanBeDestroyedByScript(bool canBeDestroyedByScript) { m_canBeDestroyedByScript = canBeDestroyedByScript; } + EventHandlerCallDispatcher& GetEventHandlerCallDispatcher() { return m_eventHandlerCallDispatcher; } + + // Iter a snapshot list of our children + // The snapshot list is inmutable, thus even if it gets modified by + // scripts it wont crash. + // If the provided `Fn` function returns bool `false` + // the given child and its sub-tree will be skipped + // + // TODO: This snapshot list stuff seems absolute bs + // Its inconsistent compared to IterAncestors + // since that function iterates the `live` version + // while this one a `snapshot` + // eg.: Parent gets changed in the middle of iteration: + // it will still iterate the old children, as the snapshot wont be updated + template + void IterChildren(const Fn& fn) + { + auto childrenSnapshot = GetChildrenListSnapshot(); + childrenSnapshot->AddRef(); + for (auto* child : *childrenSnapshot) + { + if (child->IsBeingDeleted()) + continue; + if (m_bIsBeingDeleted) + break; + // Check if the function returns a bool + if constexpr (std::is_same_v>) + { + if (!fn(child)) + continue; // Skip child and it's sub-tree + } + else + fn(child); + child->IterChildren(fn); // Recurse into child + } + childrenSnapshot->Release(); + } + + template + void IterAncestors(const Fn& fn) + { + for (CElement* it = m_pParent; it; it = it->m_pParent) + fn(it); + } + + template + void IterAncestorsThenChildren(const Fn& fn) + { + IterAncestors(fn); + IterChildren(fn); + } protected: CElement* GetRootElement(); virtual bool ReadSpecialData(const int iLine) = 0; @@ -242,12 +293,10 @@ class CElement CElement* FindChildByTypeIndex(unsigned int uiTypeHash, unsigned int uiIndex, unsigned int& uiCurrentIndex, bool bRecursive); void FindAllChildrenByTypeIndex(unsigned int uiTypeHash, lua_State* pLua, unsigned int& uiIndex); - void CallEventNoParent(const char* szName, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller = NULL); - void CallParentEvent(const char* szName, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller = NULL); - - CMapEventManager* m_pEventManager; CCustomData* m_pCustomData; + EventHandlerCallDispatcher m_eventHandlerCallDispatcher; + EElementType m_iType; ElementID m_ID; CElement* m_pParent; diff --git a/Server/mods/deathmatch/logic/CElementDeleter.cpp b/Server/mods/deathmatch/logic/CElementDeleter.cpp index 9a6aa286986..947c594a4ff 100644 --- a/Server/mods/deathmatch/logic/CElementDeleter.cpp +++ b/Server/mods/deathmatch/logic/CElementDeleter.cpp @@ -21,7 +21,7 @@ void CElementDeleter::Delete(class CElement* pElement, bool bUnlink, bool bUpdat { // Before we do anything, fire the on-destroy event CLuaArguments Arguments; - pElement->CallEvent("onElementDestroy", Arguments); + pElement->CallEvent(BuiltInEvents::onElementDestroy, Arguments); // Add it to our list if (!pElement->IsBeingDeleted()) diff --git a/Server/mods/deathmatch/logic/CEvents.cpp b/Server/mods/deathmatch/logic/CEvents.cpp deleted file mode 100644 index f16e81d72ea..00000000000 --- a/Server/mods/deathmatch/logic/CEvents.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/***************************************************************************** - * - * PROJECT: Multi Theft Auto v1.0 - * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CEvents.cpp - * PURPOSE: Event manager class - * - * Multi Theft Auto is available from http://www.multitheftauto.com/ - * - *****************************************************************************/ - -#include "StdInc.h" - -CEvents::CEvents() -{ - m_bWasEventCancelled = false; - m_bEventCancelled = false; -} - -bool CEvents::AddEvent(const char* szName, const char* szArguments, CLuaMain* pLuaMain, bool bAllowRemoteTrigger) -{ - assert(szName); - assert(szArguments); - - // If it already exists, return - if (Get(szName)) - return false; - - // Create and add the event - SEvent* pEvent = new SEvent; - pEvent->strName = szName; - pEvent->strArguments = szArguments; - pEvent->pLuaMain = pLuaMain; - pEvent->bAllowRemoteTrigger = bAllowRemoteTrigger; - - m_EventHashMap[szName] = pEvent; - - return true; -} - -void CEvents::RemoveEvent(SEvent* pEvent) -{ - assert(pEvent); - - // Remove it and delete it - MapRemove(m_EventHashMap, pEvent->strName); - delete pEvent; -} - -void CEvents::RemoveEvent(const char* szName) -{ - assert(szName); - - // Find it - SEvent* pEvent = Get(szName); - if (pEvent) - { - // Delete it - MapRemove(m_EventHashMap, pEvent->strName); - delete pEvent; - } -} - -void CEvents::RemoveAllEvents(class CLuaMain* pMain) -{ - // Delete all items - CFastHashMap::iterator iter = m_EventHashMap.begin(); - while (iter != m_EventHashMap.end()) - { - SEvent* pEvent = (*iter).second; - // If they match, delete it null it and set the bool - if (pEvent->pLuaMain == pMain) - { - // Delete the object - delete pEvent; - - // Remove from list - m_EventHashMap.erase(iter++); - } - else - ++iter; - } -} - -SEvent* CEvents::Get(const char* szName) -{ - assert(szName); - - SEvent** pEvent = MapFind(m_EventHashMap, szName); - if (pEvent != NULL) - { - return *pEvent; - } - return NULL; -} - -void CEvents::RemoveAllEvents() -{ - // Delete all items - CFastHashMap::const_iterator iter = m_EventHashMap.begin(); - for (; iter != m_EventHashMap.end(); iter++) - { - SEvent* pEvent = (*iter).second; - delete pEvent; - } - - // Clear the list - m_EventHashMap.clear(); -} - -void CEvents::PreEventPulse() -{ - m_CancelledList.push_back(m_bEventCancelled); - m_bEventCancelled = false; - m_bWasEventCancelled = false; - m_strLastError = ""; -} - -void CEvents::PostEventPulse() -{ - m_bWasEventCancelled = m_bEventCancelled; - m_bEventCancelled = m_CancelledList.back() ? true : false; - m_CancelledList.pop_back(); -} - -void CEvents::CancelEvent(bool bCancelled) -{ - m_bEventCancelled = bCancelled; -} - -void CEvents::CancelEvent(bool bCancelled, const char* szReason) -{ - m_bEventCancelled = bCancelled; - m_strLastError = SStringX(szReason); -} - -bool CEvents::WasEventCancelled() -{ - return m_bWasEventCancelled; -} - -const char* CEvents::GetLastError() -{ - return m_strLastError; -} diff --git a/Server/mods/deathmatch/logic/CEvents.h b/Server/mods/deathmatch/logic/CEvents.h deleted file mode 100644 index 2de9531f239..00000000000 --- a/Server/mods/deathmatch/logic/CEvents.h +++ /dev/null @@ -1,61 +0,0 @@ -/***************************************************************************** - * - * PROJECT: Multi Theft Auto v1.0 - * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CEvents.h - * PURPOSE: Event manager class - * - * Multi Theft Auto is available from http://www.multitheftauto.com/ - * - *****************************************************************************/ - -#pragma once - -#include -#include -#include - -struct SEvent -{ - class CLuaMain* pLuaMain; - std::string strName; - std::string strArguments; - bool bAllowRemoteTrigger; -}; - -class CEvents -{ -public: - CEvents(); - ~CEvents() { RemoveAllEvents(); }; - - bool AddEvent(const char* szName, const char* szArguments, class CLuaMain* pLuaMain, bool bAllowRemoteTrigger); - void RemoveEvent(SEvent* pEvent); - void RemoveEvent(const char* szName); - void RemoveAllEvents(class CLuaMain* pMain); - - bool Exists(const char* szName) { return Get(szName) != NULL; }; - SEvent* Get(const char* szName); - - CFastHashMap::const_iterator IterBegin() { return m_EventHashMap.begin(); }; - CFastHashMap::const_iterator IterEnd() { return m_EventHashMap.end(); }; - - void PreEventPulse(); - void PostEventPulse(); - - void CancelEvent(bool bCancelled = true); - void CancelEvent(bool bCancelled, const char* szReason); - bool WasEventCancelled(); - const char* GetLastError(); - -private: - void RemoveAllEvents(); - - CFastHashMap m_EventHashMap; - - std::vector m_CancelledList; - bool m_bEventCancelled; - bool m_bWasEventCancelled; - - SString m_strLastError; -}; diff --git a/Server/mods/deathmatch/logic/CGame.cpp b/Server/mods/deathmatch/logic/CGame.cpp index fc843054d8a..db7f9e7ba16 100644 --- a/Server/mods/deathmatch/logic/CGame.cpp +++ b/Server/mods/deathmatch/logic/CGame.cpp @@ -16,6 +16,7 @@ #include "../utils/CFunctionUseLogger.h" #include "net/SimHeaders.h" #include +#include #define MAX_BULLETSYNC_DISTANCE 400.0f #define MAX_EXPLOSION_SYNC_DISTANCE 400.0f @@ -514,13 +515,13 @@ bool CGame::Start(int iArgumentCount, char* szArguments[]) m_pScriptDebugging = new CScriptDebugging(); m_pMapManager = new CMapManager(m_pBlipManager, m_pObjectManager, m_pPickupManager, m_pPlayerManager, m_pRadarAreaManager, m_pMarkerManager, m_pVehicleManager, m_pTeamManager, m_pPedManager, m_pColManager, m_pWaterManager, m_pClock, m_pGroups, - &m_Events, m_pScriptDebugging, &m_ElementDeleter); + m_pScriptDebugging, &m_ElementDeleter); m_pACLManager = new CAccessControlListManager; m_pHqComms = new CHqComms; m_pRegisteredCommands = new CRegisteredCommands(m_pACLManager); m_pLuaManager = new CLuaManager(m_pObjectManager, m_pPlayerManager, m_pVehicleManager, m_pBlipManager, m_pRadarAreaManager, m_pRegisteredCommands, - m_pMapManager, &m_Events); + m_pMapManager); m_pConsole = new CConsole(m_pBlipManager, m_pMapManager, m_pPlayerManager, m_pRegisteredCommands, m_pVehicleManager, m_pBanManager, m_pACLManager); m_pMainConfig = new CMainConfig(m_pConsole); @@ -816,9 +817,6 @@ bool CGame::Start(int iArgumentCount, char* szArguments[]) signal(SIGPIPE, SIG_IGN); #endif - // Add our builtin events - AddBuiltInEvents(); - // Load the vehicle colors before the main config strBuffer = g_pServerInterface->GetModManager()->GetAbsolutePath("vehiclecolors.conf"); if (!m_pVehicleManager->GetColorManager()->Load(strBuffer)) @@ -1356,7 +1354,7 @@ void CGame::InitialDataStream(CPlayer& Player) // Tell our scripts the player has joined CLuaArguments Arguments; - Player.CallEvent("onPlayerJoin", Arguments); + Player.CallEvent(BuiltInEvents::onPlayerJoin, Arguments); marker.Set("onPlayerJoin"); @@ -1366,7 +1364,7 @@ void CGame::InitialDataStream(CPlayer& Player) CLuaArguments Arguments; Arguments.PushBoolean(true); Arguments.PushString(joinSecret); - Player.CallEvent("onPlayerDiscordJoin", Arguments); + Player.CallEvent(BuiltInEvents::onPlayerDiscordJoin, Arguments); } // Register them on the lightweight sync manager. @@ -1437,7 +1435,7 @@ void CGame::QuitPlayer(CPlayer& Player, CClient::eQuitReasons Reason, bool bSayI Arguments.PushBoolean(false); } - Player.CallEvent("onPlayerQuit", Arguments); + Player.CallEvent(BuiltInEvents::onPlayerQuit, Arguments); // Tell the map manager m_pMapManager->OnPlayerQuit(Player); @@ -1465,123 +1463,6 @@ void CGame::QuitPlayer(CPlayer& Player, CClient::eQuitReasons Reason, bool bSayI m_lightsyncManager.UnregisterPlayer(&Player); } -void CGame::AddBuiltInEvents() -{ - // Resource events - m_Events.AddEvent("onResourcePreStart", "resource", NULL, false); - m_Events.AddEvent("onResourceStart", "resource", NULL, false); - m_Events.AddEvent("onResourceStop", "resource, deleted", NULL, false); - m_Events.AddEvent("onResourceLoadStateChange", "resource, oldState, newState", NULL, false); - - // Blip events - - // Marker events - m_Events.AddEvent("onMarkerHit", "player, matchingDimension", NULL, false); - m_Events.AddEvent("onMarkerLeave", "player, matchingDimension", NULL, false); - - // Voice events - m_Events.AddEvent("onPlayerVoiceStart", "", NULL, false); - m_Events.AddEvent("onPlayerVoiceStop", "", NULL, false); - - // Object events - - // Pickup events - m_Events.AddEvent("onPickupHit", "player", NULL, false); - m_Events.AddEvent("onPickupLeave", "player", NULL, false); - m_Events.AddEvent("onPickupUse", "player", NULL, false); - m_Events.AddEvent("onPickupSpawn", "", NULL, false); - - // Player events - m_Events.AddEvent("onPlayerConnect", "player", NULL, false); - m_Events.AddEvent("onPlayerChat", "text", NULL, false); - m_Events.AddEvent("onPlayerDamage", "attacker, weapon, bodypart, loss", NULL, false); - m_Events.AddEvent("onPlayerVehicleEnter", "vehicle, seat, jacked", NULL, false); - m_Events.AddEvent("onPlayerVehicleExit", "vehicle, reason, jacker", NULL, false); - m_Events.AddEvent("onPlayerJoin", "", NULL, false); - m_Events.AddEvent("onPlayerQuit", "reason", NULL, false); - m_Events.AddEvent("onPlayerSpawn", "spawnpoint, team", NULL, false); - m_Events.AddEvent("onPlayerTarget", "target", NULL, false); - m_Events.AddEvent("onPlayerWasted", "ammo, killer, weapon, bodypart", NULL, false); - m_Events.AddEvent("onPlayerWeaponSwitch", "previous, current", NULL, false); - m_Events.AddEvent("onPlayerMarkerHit", "marker, matchingDimension", NULL, false); - m_Events.AddEvent("onPlayerMarkerLeave", "marker, matchingDimension", NULL, false); - m_Events.AddEvent("onPlayerPickupHit", "pickup", NULL, false); - m_Events.AddEvent("onPlayerPickupLeave", "pickup", NULL, false); - m_Events.AddEvent("onPlayerPickupUse", "pickup", NULL, false); - m_Events.AddEvent("onPlayerClick", "button, state, element, posX, posY, posZ", NULL, false); - m_Events.AddEvent("onPlayerContact", "previous, current", NULL, false); - m_Events.AddEvent("onPlayerBan", "ban", NULL, false); - m_Events.AddEvent("onPlayerLogin", "guest_account, account, auto-login", NULL, false); - m_Events.AddEvent("onPlayerLogout", "account, guest_account", NULL, false); - m_Events.AddEvent("onPlayerChangeNick", "oldnick, newnick, manuallyChanged", NULL, false); - m_Events.AddEvent("onPlayerPrivateMessage", "text, player", NULL, false); - m_Events.AddEvent("onPlayerStealthKill", "target", NULL, false); - m_Events.AddEvent("onPlayerMute", "", NULL, false); - m_Events.AddEvent("onPlayerUnmute", "", NULL, false); - m_Events.AddEvent("onPlayerCommand", "command", NULL, false); - m_Events.AddEvent("onPlayerModInfo", "filename, itemlist", NULL, false); - m_Events.AddEvent("onPlayerACInfo", "aclist, size, md5, sha256", NULL, false); - m_Events.AddEvent("onPlayerNetworkStatus", "type, ticks", NULL, false); - m_Events.AddEvent("onPlayerScreenShot", "resource, status, file_data, timestamp, tag", NULL, false); - m_Events.AddEvent("onPlayerDiscordJoin", "justConnected, secret", NULL, false); - - // Ped events - m_Events.AddEvent("onPedVehicleEnter", "vehicle, seat, jacked", NULL, false); - m_Events.AddEvent("onPedVehicleExit", "vehicle, reason, jacker", NULL, false); - m_Events.AddEvent("onPedWasted", "ammo, killer, weapon, bodypart", NULL, false); - m_Events.AddEvent("onPedWeaponSwitch", "previous, current", NULL, false); - - // Element events - m_Events.AddEvent("onElementColShapeHit", "colshape, matchingDimension", NULL, false); - m_Events.AddEvent("onElementColShapeLeave", "colshape, matchingDimension", NULL, false); - m_Events.AddEvent("onElementClicked", "button, state, clicker, posX, posY, posZ", NULL, false); - m_Events.AddEvent("onElementDataChange", "key, oldValue", NULL, false); - m_Events.AddEvent("onElementDestroy", "", NULL, false); - m_Events.AddEvent("onElementStartSync", "newSyncer", NULL, false); - m_Events.AddEvent("onElementStopSync", "oldSyncer", NULL, false); - m_Events.AddEvent("onElementModelChange", "oldModel, newModel", NULL, false); - m_Events.AddEvent("onElementDimensionChange", "oldDimension, newDimension", nullptr, false); - m_Events.AddEvent("onElementInteriorChange", "oldInterior, newInterior", nullptr, false); - - // Radar area events - - // Shape events - m_Events.AddEvent("onColShapeHit", "entity, matchingDimension", NULL, false); - m_Events.AddEvent("onColShapeLeave", "entity, matchingDimension", NULL, false); - - // Vehicle events - m_Events.AddEvent("onVehicleDamage", "loss", NULL, false); - m_Events.AddEvent("onVehicleRespawn", "exploded", NULL, false); - m_Events.AddEvent("onTrailerAttach", "towedBy", NULL, false); - m_Events.AddEvent("onTrailerDetach", "towedBy", NULL, false); - m_Events.AddEvent("onVehicleStartEnter", "player, seat, jacked", NULL, false); - m_Events.AddEvent("onVehicleStartExit", "player, seat, jacker", NULL, false); - m_Events.AddEvent("onVehicleEnter", "player, seat, jacked", NULL, false); - m_Events.AddEvent("onVehicleExit", "player, seat, jacker", NULL, false); - m_Events.AddEvent("onVehicleExplode", "", NULL, false); - - // Console events - m_Events.AddEvent("onConsole", "text", NULL, false); - - // Debug events - m_Events.AddEvent("onDebugMessage", "message, level, file, line", NULL, false); - - // Ban events - m_Events.AddEvent("onBan", "ip", NULL, false); - m_Events.AddEvent("onUnban", "ip", NULL, false); - - // Account events - m_Events.AddEvent("onAccountDataChange", "account, key, value", NULL, false); - - // Other events - m_Events.AddEvent("onSettingChange", "setting, oldValue, newValue", NULL, false); - m_Events.AddEvent("onChatMessage", "message, element", NULL, false); - - // Weapon events - m_Events.AddEvent("onWeaponFire", "", NULL, false); - m_Events.AddEvent("onPlayerWeaponFire", "weapon, endX, endY, endZ, hitElement, startX, startY, startZ", NULL, false); -} - void CGame::ProcessTrafficLights(long long llCurrentTime) { long long ulDiff = static_cast((llCurrentTime - m_llLastTrafficUpdate) * m_fGameSpeed); @@ -1966,7 +1847,7 @@ void CGame::Packet_PedWasted(CPedWastedPacket& Packet) else Arguments.PushBoolean(false); Arguments.PushBoolean(false); - pPed->CallEvent("onPedWasted", Arguments); + pPed->CallEvent(BuiltInEvents::onPedWasted, Arguments); // Reset the weapons list, because a ped loses his weapons on death for (unsigned int slot = 0; slot < WEAPON_SLOTS; ++slot) @@ -2026,7 +1907,7 @@ void CGame::Packet_PlayerWasted(CPlayerWastedPacket& Packet) else Arguments.PushBoolean(false); Arguments.PushBoolean(false); - pPlayer->CallEvent("onPlayerWasted", Arguments); + pPlayer->CallEvent(BuiltInEvents::onPlayerWasted, Arguments); // Reset the weapons list, because a player loses his weapons on death for (unsigned int slot = 0; slot < WEAPON_SLOTS; ++slot) @@ -2390,7 +2271,7 @@ void CGame::Packet_Bulletsync(CBulletsyncPacket& Packet) Arguments.PushNumber(Packet.m_vecStart.fX); Arguments.PushNumber(Packet.m_vecStart.fY); Arguments.PushNumber(Packet.m_vecStart.fZ); - pPlayer->CallEvent("onPlayerWeaponFire", Arguments); + pPlayer->CallEvent(BuiltInEvents::onPlayerWeaponFire, Arguments); } } @@ -2405,7 +2286,7 @@ void CGame::Packet_WeaponBulletsync(CCustomWeaponBulletSyncPacket& Packet) CLuaArguments Arguments; Arguments.PushElement(pPlayer); - if (pWeapon->CallEvent("onWeaponFire", Arguments)) + if (pWeapon->CallEvent(BuiltInEvents::onWeaponFire, Arguments)) { // Relay to other players m_pPlayerManager->BroadcastOnlyJoined(Packet, pPlayer); @@ -2475,7 +2356,7 @@ void CGame::Packet_LuaEvent(CLuaEventPacket& Packet) { // Grab the source player, even name, element id and the arguments passed CPlayer* pCaller = Packet.GetSourcePlayer(); - const char* szName = Packet.GetName(); + const auto& name = Packet.GetName(); ElementID ElementID = Packet.GetElementID(); CLuaArguments* pArguments = Packet.GetArguments(); @@ -2483,20 +2364,28 @@ void CGame::Packet_LuaEvent(CLuaEventPacket& Packet) CElement* pElement = CElementIDs::GetElement(ElementID); if (pElement) { - // Make sure the event exists and that it allows clientside triggering - SEvent* pEvent = m_Events.Get(szName); - if (pEvent) + if (BuiltInEvent::Get(name)) { - if (pEvent->bAllowRemoteTrigger) + // Built-in-events are not remote triggerable by default + m_pScriptDebugging->LogError(nullptr, + "Client (%s) triggered serverside event %s, but it is not marked as remotly triggerable", pCaller->GetNick(), name.c_str()); + } + else + { + if (auto* event = CustomEvent::Get(name)) { - pElement->CallEvent(szName, *pArguments, pCaller); + if (event->IsRemoteTriggerAllowed()) + pElement->CallEvent(*event, *pArguments, pCaller); + else + { + m_pScriptDebugging->LogError(nullptr, + "Client (%s) triggered serverside event %s, but it is not marked as remotly triggerable", pCaller->GetNick(), name.c_str()); + } } else - m_pScriptDebugging->LogError(NULL, "Client (%s) triggered serverside event %s, but event is not marked as remotly triggerable", - pCaller->GetNick(), szName); + m_pScriptDebugging->LogError(nullptr, + "Client (%s) triggered serverside event %s, but it is not added serverside", pCaller->GetNick(), name.c_str()); } - else - m_pScriptDebugging->LogError(NULL, "Client (%s) triggered serverside event %s, but event is not added serverside", pCaller->GetNick(), szName); } } @@ -2632,7 +2521,7 @@ void CGame::Packet_ExplosionSync(CExplosionSyncPacket& Packet) pVehicle->SetEngineOn(false); CLuaArguments Arguments; - pVehicle->CallEvent("onVehicleExplode", Arguments); + pVehicle->CallEvent(BuiltInEvents::onVehicleExplode, Arguments); bBroadcast = pVehicle->GetIsBlown() && !pVehicle->IsBeingDeleted(); } @@ -2911,7 +2800,7 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) Arguments.PushNumber(0); // seat Arguments.PushBoolean(false); // jacked Arguments.PushNumber(ucDoor); // Door - if (pVehicle->CallEvent("onVehicleStartEnter", Arguments)) + if (pVehicle->CallEvent(BuiltInEvents::onVehicleStartEnter, Arguments)) { // HACK?: check the ped's vehicle-action is still the same (not warped in?) if (pPed->GetVehicleAction() == CPed::VEHICLEACTION_ENTERING) @@ -2996,7 +2885,7 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) EnterArguments.PushNumber(0); // seat EnterArguments.PushElement(pOccupant); // jacked EnterArguments.PushNumber(ucDoor); // Door - if (pVehicle->CallEvent("onVehicleStartEnter", EnterArguments)) + if (pVehicle->CallEvent(BuiltInEvents::onVehicleStartEnter, EnterArguments)) { // HACK?: check the peds vehicle-action is still the same (not warped in?) if (pPed->GetVehicleAction() == CPed::VEHICLEACTION_JACKING) @@ -3006,7 +2895,7 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) ExitArguments.PushElement(pOccupant); // player / ped ExitArguments.PushNumber(ucSeat); // seat ExitArguments.PushElement(pPed); // jacker - if (pVehicle->CallEvent("onVehicleStartExit", ExitArguments)) + if (pVehicle->CallEvent(BuiltInEvents::onVehicleStartExit, ExitArguments)) { // HACK?: check the player's vehicle-action is still the same (not warped out?) if (pOccupant->GetVehicleAction() == CPed::VEHICLEACTION_JACKED) @@ -3058,7 +2947,7 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) Arguments.PushNumber(ucSeat); // seat Arguments.PushBoolean(false); // jacked Arguments.PushNumber(ucDoor); // Door - if (pVehicle->CallEvent("onVehicleStartEnter", Arguments)) + if (pVehicle->CallEvent(BuiltInEvents::onVehicleStartEnter, Arguments)) { // HACK?: check the player's vehicle-action is still the same (not warped in?) if (pPed->GetVehicleAction() == CPed::VEHICLEACTION_ENTERING) @@ -3162,16 +3051,16 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) Arguments.PushNumber(ucOccupiedSeat); // seat Arguments.PushBoolean(false); // jacked if (pPed->IsPlayer()) - pPed->CallEvent("onPlayerVehicleEnter", Arguments); + pPed->CallEvent(BuiltInEvents::onPlayerVehicleEnter, Arguments); else - pPed->CallEvent("onPedVehicleEnter", Arguments); + pPed->CallEvent(BuiltInEvents::onPedVehicleEnter, Arguments); // Call the vehicle->player event CLuaArguments Arguments2; Arguments2.PushElement(pPed); // player / ped Arguments2.PushNumber(ucOccupiedSeat); // seat Arguments2.PushBoolean(false); // jacked - pVehicle->CallEvent("onVehicleEnter", Arguments2); + pVehicle->CallEvent(BuiltInEvents::onVehicleEnter, Arguments2); } } @@ -3231,7 +3120,7 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) Arguments.PushNumber(ucOccupiedSeat); // seat Arguments.PushBoolean(false); // jacked Arguments.PushNumber(Packet.GetDoor()); // door being used - if (pVehicle->CallEvent("onVehicleStartExit", Arguments) && pPed->GetOccupiedVehicle() == pVehicle) + if (pVehicle->CallEvent(BuiltInEvents::onVehicleStartExit, Arguments) && pPed->GetOccupiedVehicle() == pVehicle) { // Mark him as exiting the vehicle pPed->SetVehicleAction(CPed::VEHICLEACTION_EXITING); @@ -3301,9 +3190,9 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) Arguments.PushBoolean(false); // jacker Arguments.PushBoolean(false); // forcedByScript if (pPed->IsPlayer()) - pPed->CallEvent("onPlayerVehicleExit", Arguments); + pPed->CallEvent(BuiltInEvents::onPlayerVehicleExit, Arguments); else - pPed->CallEvent("onPedVehicleExit", Arguments); + pPed->CallEvent(BuiltInEvents::onPedVehicleExit, Arguments); // Call the vehicle->player event CLuaArguments Arguments2; @@ -3311,7 +3200,7 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) Arguments2.PushNumber(ucOccupiedSeat); // seat Arguments2.PushBoolean(false); // jacker Arguments2.PushBoolean(false); // forcedByScript - pVehicle->CallEvent("onVehicleExit", Arguments2); + pVehicle->CallEvent(BuiltInEvents::onVehicleExit, Arguments2); } } @@ -3366,11 +3255,11 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) Arguments.PushBoolean(false); // forcedByScript if (pPed->IsPlayer()) { - pPed->CallEvent("onPlayerVehicleExit", Arguments); + pPed->CallEvent(BuiltInEvents::onPlayerVehicleExit, Arguments); } else { - pPed->CallEvent("onPedVehicleExit", Arguments); + pPed->CallEvent(BuiltInEvents::onPedVehicleExit, Arguments); } // Call the vehicle->player event @@ -3379,7 +3268,7 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) Arguments2.PushNumber(ucOccupiedSeat); // seat Arguments2.PushBoolean(false); // jacker Arguments2.PushBoolean(false); // forcedByScript - pVehicle->CallEvent("onVehicleExit", Arguments2); + pVehicle->CallEvent(BuiltInEvents::onVehicleExit, Arguments2); } break; @@ -3417,9 +3306,9 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) ArgumentsExit.PushElement(pPed); // jacker ArgumentsExit.PushBoolean(false); // forcedByScript if (pJacked->IsPlayer()) - pJacked->CallEvent("onPlayerVehicleExit", ArgumentsExit); + pJacked->CallEvent(BuiltInEvents::onPlayerVehicleExit, ArgumentsExit); else - pJacked->CallEvent("onPedVehicleExit", ArgumentsExit); + pJacked->CallEvent(BuiltInEvents::onPedVehicleExit, ArgumentsExit); // Execute the vehicle->ped script function for the jacked ped CLuaArguments ArgumentsExit2; @@ -3427,7 +3316,7 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) ArgumentsExit2.PushNumber(0); // seat ArgumentsExit2.PushElement(pPed); // jacker ArgumentsExit2.PushBoolean(false); // forcedByScript - pVehicle->CallEvent("onVehicleExit", ArgumentsExit2); + pVehicle->CallEvent(BuiltInEvents::onVehicleExit, ArgumentsExit2); // Execute the ped->vehicle script function CLuaArguments ArgumentsEnter; @@ -3435,16 +3324,16 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) ArgumentsEnter.PushNumber(0); // seat ArgumentsEnter.PushElement(pJacked); // jacked if (pPed->IsPlayer()) - pPed->CallEvent("onPlayerVehicleEnter", ArgumentsEnter); + pPed->CallEvent(BuiltInEvents::onPlayerVehicleEnter, ArgumentsEnter); else - pPed->CallEvent("onPedVehicleEnter", ArgumentsEnter); + pPed->CallEvent(BuiltInEvents::onPedVehicleEnter, ArgumentsEnter); // Execute the vehicle->ped script function CLuaArguments ArgumentsEnter2; ArgumentsEnter2.PushElement(pPed); // player / ped ArgumentsEnter2.PushNumber(0); // seat ArgumentsEnter2.PushElement(pJacked); // jacked - pVehicle->CallEvent("onVehicleEnter", ArgumentsEnter2); + pVehicle->CallEvent(BuiltInEvents::onVehicleEnter, ArgumentsEnter2); } else { @@ -3464,16 +3353,16 @@ void CGame::Packet_Vehicle_InOut(CVehicleInOutPacket& Packet) Arguments.PushNumber(0); // seat Arguments.PushBoolean(false); // jacked if (pPed->IsPlayer()) - pPed->CallEvent("onPlayerVehicleEnter", Arguments); + pPed->CallEvent(BuiltInEvents::onPlayerVehicleEnter, Arguments); else - pPed->CallEvent("onPedVehicleEnter", Arguments); + pPed->CallEvent(BuiltInEvents::onPedVehicleEnter, Arguments); // Execute the vehicle->player script function CLuaArguments Arguments2; Arguments2.PushElement(pPed); // player / ped Arguments2.PushNumber(0); // seat Arguments2.PushBoolean(false); // jacked - pVehicle->CallEvent("onVehicleEnter", Arguments2); + pVehicle->CallEvent(BuiltInEvents::onVehicleEnter, Arguments2); } if (!sendListIncompatiblePlayers.empty()) @@ -3631,7 +3520,7 @@ void CGame::Packet_VehicleTrailer(CVehicleTrailerPacket& Packet) // Execute the attach trailer script function CLuaArguments Arguments; Arguments.PushElement(pVehicle); - bool bContinue = pTrailer->CallEvent("onTrailerAttach", Arguments); + bool bContinue = pTrailer->CallEvent(BuiltInEvents::onTrailerAttach, Arguments); if (!bContinue) { @@ -3656,7 +3545,7 @@ void CGame::Packet_VehicleTrailer(CVehicleTrailerPacket& Packet) // Execute the detach trailer script function CLuaArguments Arguments; Arguments.PushElement(pVehicle); - pTrailer->CallEvent("onTrailerDetach", Arguments); + pTrailer->CallEvent(BuiltInEvents::onTrailerDetach, Arguments); } } } @@ -3687,7 +3576,7 @@ void CGame::Packet_Voice_Data(CVoiceDataPacket& Packet) { // Trigger the related event CLuaArguments Arguments; - bool bEventTriggered = pPlayer->CallEvent("onPlayerVoiceStart", Arguments, pPlayer); + bool bEventTriggered = pPlayer->CallEvent(BuiltInEvents::onPlayerVoiceStart, Arguments, pPlayer); if (!bEventTriggered) // Was the event cancelled? { @@ -3763,7 +3652,7 @@ void CGame::Packet_Voice_End(CVoiceEndPacket& Packet) if (pPlayer) { CLuaArguments Arguments; - pPlayer->CallEvent("onPlayerVoiceStop", Arguments, pPlayer); + pPlayer->CallEvent(BuiltInEvents::onPlayerVoiceStop, Arguments, pPlayer); // Reset our voice state pPlayer->SetVoiceState(VOICESTATE_IDLE); @@ -3901,7 +3790,7 @@ void CGame::Packet_PlayerScreenShot(CPlayerScreenShotPacket& Packet) Arguments.PushNumber(static_cast(Packet.m_llServerGrabTime)); Arguments.PushString(Packet.m_strTag); Arguments.PushString(Packet.m_strError); - pPlayer->CallEvent("onPlayerScreenShot", Arguments); + pPlayer->CallEvent(BuiltInEvents::onPlayerScreenShot, Arguments); } } else if (Packet.m_ucStatus == EPlayerScreenShotResult::SUCCESS) @@ -3948,7 +3837,7 @@ void CGame::Packet_PlayerScreenShot(CPlayerScreenShotPacket& Packet) Arguments.PushString(std::string(info.buffer.GetData(), info.buffer.GetSize())); Arguments.PushNumber(static_cast(info.llTimeStamp)); Arguments.PushString(info.strTag); - pPlayer->CallEvent("onPlayerScreenShot", Arguments); + pPlayer->CallEvent(BuiltInEvents::onPlayerScreenShot, Arguments); } info.bInProgress = false; @@ -3983,7 +3872,7 @@ void CGame::Packet_PlayerNetworkStatus(CPlayerNetworkStatusPacket& Packet) CLuaArguments Arguments; Arguments.PushNumber(Packet.m_ucType); // 0-interruption began 1-interruption end Arguments.PushNumber(Packet.m_uiTicks); // Ticks since interruption start - pPlayer->CallEvent("onPlayerNetworkStatus", Arguments, NULL); + pPlayer->CallEvent(BuiltInEvents::onPlayerNetworkStatus, Arguments, NULL); } } @@ -3995,7 +3884,7 @@ void CGame::Packet_DiscordJoin(CDiscordJoinPacket& Packet) CLuaArguments Arguments; Arguments.PushBoolean(false); Arguments.PushString(Packet.GetSecret()); - pPlayer->CallEvent("onPlayerDiscordJoin", Arguments, NULL); + pPlayer->CallEvent(BuiltInEvents::onPlayerDiscordJoin, Arguments, NULL); } } @@ -4071,7 +3960,7 @@ void CGame::Packet_PlayerModInfo(CPlayerModInfoPacket& Packet) CLuaArguments Arguments; Arguments.PushString(Packet.m_strInfoType); Arguments.PushTable(&resultItemList); - pPlayer->CallEvent("onPlayerModInfo", Arguments); + pPlayer->CallEvent(BuiltInEvents::onPlayerModInfo, Arguments); } } @@ -4092,7 +3981,7 @@ void CGame::Packet_PlayerACInfo(CPlayerACInfoPacket& Packet) Arguments.PushNumber(Packet.m_uiD3d9Size); Arguments.PushString(Packet.m_strD3d9MD5); Arguments.PushString(Packet.m_strD3d9SHA256); - pPlayer->CallEvent("onPlayerACInfo", Arguments); + pPlayer->CallEvent(BuiltInEvents::onPlayerACInfo, Arguments); } } @@ -4107,17 +3996,14 @@ void CGame::PlayerCompleteConnect(CPlayer* pPlayer) Arguments.PushString(pPlayer->GetSerial().c_str()); Arguments.PushNumber(pPlayer->GetMTAVersion()); Arguments.PushString(pPlayer->GetPlayerVersion()); - if (!g_pGame->GetMapManager()->GetRootElement()->CallEvent("onPlayerConnect", Arguments)) + if (!g_pGame->GetMapManager()->GetRootElement()->CallEvent(BuiltInEvents::onPlayerConnect, Arguments)) { // event cancelled, disconnect the player CLogger::LogPrintf("CONNECT: %s failed to connect. (onPlayerConnect event cancelled) (%s)\n", pPlayer->GetNick(), strIPAndSerial.c_str()); - const char* szError = g_pGame->GetEvents()->GetLastError(); - if (szError && szError[0]) - { - DisconnectPlayer(g_pGame, *pPlayer, szError); - return; - } - DisconnectPlayer(g_pGame, *pPlayer, CPlayerDisconnectedPacket::GENERAL_REFUSED); + if (const std::string& reason = s_EventDispatcher.GetCancelReason(); !reason.empty()) + DisconnectPlayer(g_pGame, *pPlayer, reason.c_str()); + else + DisconnectPlayer(g_pGame, *pPlayer, CPlayerDisconnectedPacket::GENERAL_REFUSED); return; } diff --git a/Server/mods/deathmatch/logic/CGame.h b/Server/mods/deathmatch/logic/CGame.h index f8ab006cb05..0e0a43149b4 100644 --- a/Server/mods/deathmatch/logic/CGame.h +++ b/Server/mods/deathmatch/logic/CGame.h @@ -16,7 +16,6 @@ class CGame; #include "CCommon.h" #include #include "CClient.h" -#include "CEvents.h" #include "CCommandLineParser.h" #include "CConnectHistory.h" #include "CElementDeleter.h" @@ -224,7 +223,6 @@ class CGame CRegistry* GetRegistry() { return m_pRegistry; } CAccountManager* GetAccountManager() { return m_pAccountManager; } CScriptDebugging* GetScriptDebugging() { return m_pScriptDebugging; } - CEvents* GetEvents() { return &m_Events; } CColManager* GetColManager() { return m_pColManager; } CLatentTransferManager* GetLatentTransferManager() { return m_pLatentTransferManager; } CDebugHookManager* GetDebugHookManager() { return m_pDebugHookManager; } @@ -463,7 +461,6 @@ class CGame void SetClientTransferBoxVisible(bool visible) { m_showClientTransferBox = visible; } private: - void AddBuiltInEvents(); void RelayPlayerPuresync(class CPacket& Packet); void RelayNearbyPacket(class CPacket& Packet); @@ -508,7 +505,6 @@ class CGame // Technically, this could be put somewhere else. It's a callback function // which the voice server library will call to send out data. - CEvents m_Events; CRemoteCalls* m_pRemoteCalls; CHTTPD* m_pHTTPD; CMainConfig* m_pMainConfig; diff --git a/Server/mods/deathmatch/logic/CGroups.cpp b/Server/mods/deathmatch/logic/CGroups.cpp index da0f2bba2b1..ce5a42dbb92 100644 --- a/Server/mods/deathmatch/logic/CGroups.cpp +++ b/Server/mods/deathmatch/logic/CGroups.cpp @@ -16,11 +16,11 @@ CDummy* CGroups::Create(CElement* pParent) return new CDummy(this, pParent); } -CDummy* CGroups::CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents) +CDummy* CGroups::CreateFromXML(CElement* pParent, CXMLNode& Node) { CDummy* const pTemp = new CDummy(this, pParent); - if (!pTemp->LoadFromCustomData(pEvents, Node)) + if (!pTemp->LoadFromCustomData(Node)) { delete pTemp; return nullptr; diff --git a/Server/mods/deathmatch/logic/CGroups.h b/Server/mods/deathmatch/logic/CGroups.h index 8966c88a210..f3b5d51949e 100644 --- a/Server/mods/deathmatch/logic/CGroups.h +++ b/Server/mods/deathmatch/logic/CGroups.h @@ -24,7 +24,7 @@ class CGroups ~CGroups() { DeleteAll(); } CDummy* Create(CElement* pParent); - CDummy* CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents); + CDummy* CreateFromXML(CElement* pParent, CXMLNode& Node); void Delete(CDummy* pDummy); void DeleteAll(); diff --git a/Server/mods/deathmatch/logic/CMapEvent.cpp b/Server/mods/deathmatch/logic/CMapEvent.cpp deleted file mode 100644 index 847c5c97b1a..00000000000 --- a/Server/mods/deathmatch/logic/CMapEvent.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/***************************************************************************** - * - * PROJECT: Multi Theft Auto v1.0 - * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CMapEvent.cpp - * PURPOSE: Map event class - * - * Multi Theft Auto is available from http://www.multitheftauto.com/ - * - *****************************************************************************/ - -#include "StdInc.h" - -CMapEvent::CMapEvent(CLuaMain* pMain, const char* szName, const CLuaFunctionRef& iLuaFunction, bool bPropagated, EEventPriorityType eventPriority, - float fPriorityMod) -{ - // Init - m_pMain = pMain; - m_bDestroyFunction = false; - m_iLuaFunction = iLuaFunction; - m_bPropagated = bPropagated; - m_bBeingDestroyed = false; - m_eventPriority = eventPriority; - m_fPriorityMod = fPriorityMod; - m_strName.AssignLeft(szName, MAPEVENT_MAX_LENGTH_NAME); -} - -CMapEvent::~CMapEvent() -{ -} - -void CMapEvent::Call(const CLuaArguments& Arguments) -{ - if (m_pMain) - { - // Call our function with the given arguments - Arguments.Call(m_pMain, m_iLuaFunction); - } -} - -bool CMapEvent::IsHigherPriorityThan(const CMapEvent* pOther) -{ - return m_eventPriority > pOther->m_eventPriority || (m_eventPriority == pOther->m_eventPriority && m_fPriorityMod > pOther->m_fPriorityMod); -} diff --git a/Server/mods/deathmatch/logic/CMapEvent.h b/Server/mods/deathmatch/logic/CMapEvent.h deleted file mode 100644 index 6cc8129ae45..00000000000 --- a/Server/mods/deathmatch/logic/CMapEvent.h +++ /dev/null @@ -1,48 +0,0 @@ -/***************************************************************************** - * - * PROJECT: Multi Theft Auto v1.0 - * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CMapEvent.h - * PURPOSE: Map event class - * - * Multi Theft Auto is available from http://www.multitheftauto.com/ - * - *****************************************************************************/ - -#pragma once - -#define MAPEVENT_MAX_LENGTH_NAME 100 - -#include -#include - -class CMapEvent -{ - friend class CMapEventManager; - -public: - class CLuaMain* GetVM() { return m_pMain; }; - const SString& GetName() { return m_strName; }; - const CLuaFunctionRef& GetLuaFunction() { return m_iLuaFunction; }; - bool IsPropagated() { return m_bPropagated; } - bool IsBeingDestroyed() { return m_bBeingDestroyed; } - - void Call(const class CLuaArguments& Arguments); - bool IsHigherPriorityThan(const CMapEvent* pOther); - -private: - CMapEvent(class CLuaMain* pMain, const char* szName, const CLuaFunctionRef& iLuaFunction, bool bPropagated, EEventPriorityType eventPriority, - float fPriorityMod); - ~CMapEvent(); - - void SetBeingDestroyed(bool bBeingDestroyed) { m_bBeingDestroyed = bBeingDestroyed; } - - class CLuaMain* m_pMain; - CLuaFunctionRef m_iLuaFunction; - SString m_strName; - bool m_bPropagated; - bool m_bDestroyFunction; - bool m_bBeingDestroyed; - EEventPriorityType m_eventPriority; - float m_fPriorityMod; -}; diff --git a/Server/mods/deathmatch/logic/CMapEventManager.cpp b/Server/mods/deathmatch/logic/CMapEventManager.cpp deleted file mode 100644 index 60e844d1f4f..00000000000 --- a/Server/mods/deathmatch/logic/CMapEventManager.cpp +++ /dev/null @@ -1,382 +0,0 @@ -/***************************************************************************** - * - * PROJECT: Multi Theft Auto v1.0 - * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CMapEventManager.cpp - * PURPOSE: Map event manager class - * - * Multi Theft Auto is available from http://www.multitheftauto.com/ - * - *****************************************************************************/ - -#include "StdInc.h" - -CMapEventManager::CMapEventManager() -{ - m_bIteratingList = false; - m_bHasEvents = false; -} - -CMapEventManager::~CMapEventManager() -{ - // If this happens while we're iterating the list, we're screwed - assert(!m_bIteratingList); - - // This should always be empty when m_bIteratingList is false - assert(m_TrashCan.empty()); - - // Delete all eventhandlers - DeleteAll(); -} - -bool CMapEventManager::Add(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction, bool bPropagated, EEventPriorityType eventPriority, - float fPriorityMod) -{ - // Check for max name length - if (strlen(szName) <= MAPEVENT_MAX_LENGTH_NAME) - { - // Make a new event - CMapEvent* pEvent = new CMapEvent(pLuaMain, szName, iLuaFunction, bPropagated, eventPriority, fPriorityMod); - - // Add now - AddInternal(pEvent); - - m_bHasEvents = true; - return true; - } - return false; -} - -bool CMapEventManager::Delete(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction) -{ - // Delete all the events with matching names - bool bRemovedSomeone = false; - - EventsIter iter = m_EventsMap.begin(); - while (iter != m_EventsMap.end()) - { - CMapEvent* pMapEvent = iter->second; - - // Matching VM? - if (pLuaMain == pMapEvent->GetVM()) - { - // If name supplied, check name and function - if (!szName || ((strcmp(pMapEvent->GetName(), szName) == 0) && (pMapEvent->GetLuaFunction() == iLuaFunction))) - { - // Not alredy being destroyed? - if (!pMapEvent->IsBeingDestroyed()) - { - // Are we in an event handler? - if (m_bIteratingList) - { - // Put it in the trashcan - pMapEvent->SetBeingDestroyed(true); - m_TrashCan.push_back(pMapEvent); - - // Remember that we deleted something - bRemovedSomeone = true; - } - else - { - // Delete the object - delete pMapEvent; - - // Remove from list and remember that we deleted something - m_EventsMap.erase(iter++); - bRemovedSomeone = true; - continue; - } - } - } - } - - // Increment iterator - ++iter; - } - - m_bHasEvents = !m_EventsMap.empty(); - - // Return whether we actually destroyed someone or not - return bRemovedSomeone; -} - -void CMapEventManager::DeleteAll() -{ - // Delete all the events - EventsIter iter = m_EventsMap.begin(); - while (iter != m_EventsMap.end()) - { - CMapEvent* pMapEvent = iter->second; - - // Delete it if it's not already being destroyed - if (!pMapEvent->IsBeingDestroyed()) - { - delete pMapEvent; - m_EventsMap.erase(iter++); - } - else - ++iter; - } - m_bHasEvents = !m_EventsMap.empty(); -} - -bool CMapEventManager::Call(const char* szName, const CLuaArguments& Arguments, class CElement* pSource, class CElement* pThis, CPlayer* pCaller) -{ - // Check if no events - if (!m_bHasEvents) - return false; - - // Check if no events with a name match - EventsIterPair itPair = m_EventsMap.equal_range(szName); - if (itPair.first == itPair.second) - return false; - - // Call all the events with matching names - bool bCalled = false; - bool bIsAlreadyIterating = m_bIteratingList; - m_bIteratingList = true; - - // Copy the results into a array in case m_EventsMap is modified during the call - std::vector matchingEvents; - for (EventsIter iter = itPair.first; iter != itPair.second; ++iter) - matchingEvents.push_back(iter->second); - - for (std::vector::iterator iter = matchingEvents.begin(); iter != matchingEvents.end(); ++iter) - { - CMapEvent* pMapEvent = *iter; - - // If it's not being destroyed - if (!pMapEvent->IsBeingDestroyed()) - { - // Compare the names - dassert(strcmp(pMapEvent->GetName(), szName) == 0); - { - // Call if propagated? - if (pSource == pThis || pMapEvent->IsPropagated()) - { - // Grab the current VM - lua_State* pState = pMapEvent->GetVM()->GetVM(); - - LUA_CHECKSTACK(pState, 1); // Ensure some room - - #if MTA_DEBUG - int luaStackPointer = lua_gettop(pState); - #endif - - TIMEUS startTime = GetTimeUs(); - - if (!g_pGame->GetDebugHookManager()->OnPreEventFunction(szName, Arguments, pSource, pCaller, pMapEvent)) - continue; - - // Store the current values of the globals - lua_getglobal(pState, "source"); - CLuaArgument OldSource(pState, -1); - lua_pop(pState, 1); - - lua_getglobal(pState, "this"); - CLuaArgument OldThis(pState, -1); - lua_pop(pState, 1); - - lua_getglobal(pState, "sourceResource"); - CLuaArgument OldResource(pState, -1); - lua_pop(pState, 1); - - lua_getglobal(pState, "sourceResourceRoot"); - CLuaArgument OldResourceRoot(pState, -1); - lua_pop(pState, 1); - - lua_getglobal(pState, "eventName"); - CLuaArgument OldEventName(pState, -1); - lua_pop(pState, 1); - - lua_getglobal(pState, "client"); - CLuaArgument OldClient(pState, -1); - lua_pop(pState, 1); - - // Set the "source", "this", "sourceResource" and "sourceResourceRoot" globals on that VM - lua_pushelement(pState, pSource); - lua_setglobal(pState, "source"); - - lua_pushelement(pState, pThis); - lua_setglobal(pState, "this"); - - CLuaMain* pLuaMain = g_pGame->GetScriptDebugging()->GetTopLuaMain(); - CResource* pSourceResource = pLuaMain ? pLuaMain->GetResource() : NULL; - if (pSourceResource) - { - lua_pushresource(pState, pSourceResource); - lua_setglobal(pState, "sourceResource"); - - lua_pushelement(pState, pSourceResource->GetResourceRootElement()); - lua_setglobal(pState, "sourceResourceRoot"); - } - else - { - lua_pushnil(pState); - lua_setglobal(pState, "sourceResource"); - - lua_pushnil(pState); - lua_setglobal(pState, "sourceResourceRoot"); - } - - lua_pushstring(pState, szName); - lua_setglobal(pState, "eventName"); - - if (pCaller) - { - lua_pushelement(pState, pCaller); - lua_setglobal(pState, "client"); - } - else - { - lua_pushnil(pState); - lua_setglobal(pState, "client"); - } - - // Call it - pMapEvent->Call(Arguments); - bCalled = true; - - g_pGame->GetDebugHookManager()->OnPostEventFunction(szName, Arguments, pSource, pCaller, pMapEvent); - - // Reset the globals on that VM - OldSource.Push(pState); - lua_setglobal(pState, "source"); - - OldThis.Push(pState); - lua_setglobal(pState, "this"); - - OldResource.Push(pState); - lua_setglobal(pState, "sourceResource"); - - OldResourceRoot.Push(pState); - lua_setglobal(pState, "sourceResourceRoot"); - - OldEventName.Push(pState); - lua_setglobal(pState, "eventName"); - - OldClient.Push(pState); - lua_setglobal(pState, "client"); - - #if MTA_DEBUG - assert(lua_gettop(pState) == luaStackPointer); - #endif - - CPerfStatLuaTiming::GetSingleton()->UpdateLuaTiming(pMapEvent->GetVM(), szName, GetTimeUs() - startTime); - } - } - } - } - - // Clean out the trash if we're no longer calling events. - if (!bIsAlreadyIterating) - { - TakeOutTheTrash(); - - // We're no longer iterating the list - m_bIteratingList = false; - } - - // Return whether we called atleast one func or not - return bCalled; -} - -void CMapEventManager::TakeOutTheTrash() -{ - // Loop through our trashcan deleting every item - std::list::const_iterator iterTrash = m_TrashCan.begin(); - for (; iterTrash != m_TrashCan.end(); iterTrash++) - { - CMapEvent* pMapEvent = *iterTrash; - - // Remove from the eventhandler list - EventsIter iterMap = m_EventsMap.begin(); - while (iterMap != m_EventsMap.end()) - { - if (pMapEvent == iterMap->second) - m_EventsMap.erase(iterMap++); - else - ++iterMap; - } - - // Delete it - delete pMapEvent; - } - - m_bHasEvents = !m_EventsMap.empty(); - - // Clear the trashcan - m_TrashCan.clear(); -} - -bool CMapEventManager::HandleExists(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction) -{ - // Return true if we find an event which matches the handle - EventsIterPair itPair = m_EventsMap.equal_range(szName); - for (EventsIter iter = itPair.first; iter != itPair.second; ++iter) - { - CMapEvent* pMapEvent = iter->second; - - // Is it not being destroyed? - if (!pMapEvent->IsBeingDestroyed()) - { - // Same lua main? - if (pMapEvent->GetVM() == pLuaMain) - { - // Same name? - dassert(strcmp(pMapEvent->GetName(), szName) == 0); - { - // Same lua function? - if (pMapEvent->GetLuaFunction() == iLuaFunction) - { - // It exists - return true; - } - } - } - } - } - - // Doesn't exist - return false; -} - -void CMapEventManager::AddInternal(CMapEvent* pEvent) -{ - // Find place to insert - EventsIterPair itPair = m_EventsMap.equal_range(pEvent->GetName()); - EventsIter iter; - for (iter = itPair.first; iter != itPair.second; ++iter) - { - if (pEvent->IsHigherPriorityThan(iter->second)) - break; - } - // Do insert - m_EventsMap.insert(iter, std::pair(pEvent->GetName(), pEvent)); -} - -void CMapEventManager::GetHandles(CLuaMain* pLuaMain, const char* szName, lua_State* luaVM) -{ - unsigned int uiIndex = 0; - EventsIterPair itPair = m_EventsMap.equal_range(szName); - for (EventsIter iter = itPair.first; iter != itPair.second; ++iter) - { - CMapEvent* pMapEvent = iter->second; - - // Is it not being destroyed? - if (!pMapEvent->IsBeingDestroyed()) - { - // Same lua main? - if (pMapEvent->GetVM() == pLuaMain) - { - // Same name? - dassert(strcmp(pMapEvent->GetName(), szName) == 0); - { - lua_pushnumber(luaVM, ++uiIndex); - lua_getref(luaVM, pMapEvent->GetLuaFunction().ToInt()); - lua_settable(luaVM, -3); - } - } - } - } -} \ No newline at end of file diff --git a/Server/mods/deathmatch/logic/CMapEventManager.h b/Server/mods/deathmatch/logic/CMapEventManager.h deleted file mode 100644 index 5859a69c840..00000000000 --- a/Server/mods/deathmatch/logic/CMapEventManager.h +++ /dev/null @@ -1,47 +0,0 @@ -/***************************************************************************** - * - * PROJECT: Multi Theft Auto v1.0 - * LICENSE: See LICENSE in the top level directory - * FILE: mods/deathmatch/logic/CMapEventManager.h - * PURPOSE: Map event manager class - * - * Multi Theft Auto is available from http://www.multitheftauto.com/ - * - *****************************************************************************/ - -#pragma once - -#include "lua/CLuaArguments.h" -#include "CMapEvent.h" -#include - -class CMapEventManager -{ -public: - CMapEventManager(); - ~CMapEventManager(); - - bool Add(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction, bool bPropagated, EEventPriorityType eventPriority, - float fPriorityMod); - bool Delete(CLuaMain* pLuaMain, const char* szName = NULL, const CLuaFunctionRef& iLuaFunction = CLuaFunctionRef()); - void DeleteAll(); - bool HandleExists(CLuaMain* pLuaMain, const char* szName, const CLuaFunctionRef& iLuaFunction); - bool HasEvents() const { return m_bHasEvents; } - void GetHandles(CLuaMain* pLuaMain, const char* szName, lua_State* luaVM); - - bool Call(const char* szName, const CLuaArguments& Arguments, class CElement* pSource, class CElement* pThis, class CPlayer* pCaller = NULL); - -private: - void TakeOutTheTrash(); - void AddInternal(CMapEvent* pEvent); - - bool m_bHasEvents; - bool m_bIteratingList; - std::multimap m_EventsMap; - std::list m_TrashCan; - - // Types for m_EventsMap access - typedef std::multimap::const_iterator EventsConstIter; - typedef std::multimap::iterator EventsIter; - typedef std::pair EventsIterPair; -}; diff --git a/Server/mods/deathmatch/logic/CMapManager.cpp b/Server/mods/deathmatch/logic/CMapManager.cpp index 4debe64d676..c0c36fdcc76 100644 --- a/Server/mods/deathmatch/logic/CMapManager.cpp +++ b/Server/mods/deathmatch/logic/CMapManager.cpp @@ -16,7 +16,7 @@ extern CGame* g_pGame; CMapManager::CMapManager(CBlipManager* pBlipManager, CObjectManager* pObjectManager, CPickupManager* pPickupManager, CPlayerManager* pPlayerManager, CRadarAreaManager* pRadarAreaManager, CMarkerManager* pMarkerManager, CVehicleManager* pVehicleManager, CTeamManager* pTeamManager, CPedManager* pPedManager, CColManager* pColManager, CWaterManager* pWaterManager, CClock* pClock, - CGroups* pGroups, CEvents* pEvents, class CScriptDebugging* pScriptDebugging, CElementDeleter* pElementDeleter) + CGroups* pGroups, class CScriptDebugging* pScriptDebugging, CElementDeleter* pElementDeleter) { // Init m_pBlipManager = pBlipManager; @@ -32,7 +32,6 @@ CMapManager::CMapManager(CBlipManager* pBlipManager, CObjectManager* pObjectMana m_pWaterManager = pWaterManager; m_pServerClock = pClock; m_pGroups = pGroups; - m_pEvents = pEvents; m_pScriptDebugging = pScriptDebugging; m_pElementDeleter = pElementDeleter; @@ -608,7 +607,7 @@ void CMapManager::SpawnPlayer(CPlayer& Player, const CVector& vecPosition, float OnPlayerSpawnArguments.PushNumber(usModel); OnPlayerSpawnArguments.PushNumber(ucInterior); OnPlayerSpawnArguments.PushNumber(usDimension); - Player.CallEvent("onPlayerSpawn", OnPlayerSpawnArguments); + Player.CallEvent(BuiltInEvents::onPlayerSpawn, OnPlayerSpawnArguments); } void CMapManager::DoRespawning() @@ -671,7 +670,7 @@ void CMapManager::DoPickupRespawning() // Call the on pickup spawn event CLuaArguments Arguments; - pPickup->CallEvent("onPickupSpawn", Arguments); + pPickup->CallEvent(BuiltInEvents::onPickupSpawn, Arguments); } } } @@ -801,7 +800,7 @@ void CMapManager::DoVehicleRespawning() // Call the respawn event CLuaArguments Arguments; Arguments.PushBoolean(bExploded); - pVehicle->CallEvent("onVehicleRespawn", Arguments); + pVehicle->CallEvent(BuiltInEvents::onVehicleRespawn, Arguments); } } @@ -853,16 +852,16 @@ bool CMapManager::HandleNode(CResource& Loader, CXMLNode& Node, CElement* pParen CElement* pNode = NULL; if (elementType == CElement::VEHICLE) { - pNode = m_pVehicleManager->CreateFromXML(pParent, Node, m_pEvents); + pNode = m_pVehicleManager->CreateFromXML(pParent, Node); } else if (elementType == CElement::OBJECT) { bool bIsLowLod = false; - pNode = m_pObjectManager->CreateFromXML(pParent, Node, m_pEvents, bIsLowLod); + pNode = m_pObjectManager->CreateFromXML(pParent, Node, bIsLowLod); } else if (elementType == CElement::BLIP) { - CBlip* pBlip = m_pBlipManager->CreateFromXML(pParent, Node, m_pEvents); + CBlip* pBlip = m_pBlipManager->CreateFromXML(pParent, Node); pNode = pBlip; /*if ( pBlip ) { @@ -871,11 +870,11 @@ bool CMapManager::HandleNode(CResource& Loader, CXMLNode& Node, CElement* pParen } else if (elementType == CElement::PICKUP) { - pNode = m_pPickupManager->CreateFromXML(pParent, Node, m_pEvents); + pNode = m_pPickupManager->CreateFromXML(pParent, Node); } else if (elementType == CElement::MARKER) { - CMarker* pMarker = m_pMarkerManager->CreateFromXML(pParent, Node, m_pEvents); + CMarker* pMarker = m_pMarkerManager->CreateFromXML(pParent, Node); pNode = pMarker; if (pMarker) { @@ -884,7 +883,7 @@ bool CMapManager::HandleNode(CResource& Loader, CXMLNode& Node, CElement* pParen } else if (elementType == CElement::RADAR_AREA) { - CRadarArea* pRadarArea = m_pRadarAreaManager->CreateFromXML(pParent, Node, m_pEvents); + CRadarArea* pRadarArea = m_pRadarAreaManager->CreateFromXML(pParent, Node); pNode = pRadarArea; if (pRadarArea) { @@ -893,15 +892,15 @@ bool CMapManager::HandleNode(CResource& Loader, CXMLNode& Node, CElement* pParen } else if (elementType == CElement::TEAM) { - pNode = m_pTeamManager->CreateFromXML(pParent, Node, m_pEvents); + pNode = m_pTeamManager->CreateFromXML(pParent, Node); } else if (elementType == CElement::PED) { - pNode = m_pPedManager->CreateFromXML(pParent, Node, m_pEvents); + pNode = m_pPedManager->CreateFromXML(pParent, Node); } else if (elementType == CElement::WATER) { - pNode = m_pWaterManager->CreateFromXML(pParent, Node, m_pEvents); + pNode = m_pWaterManager->CreateFromXML(pParent, Node); } else if (strBuffer.empty()) { @@ -910,7 +909,7 @@ bool CMapManager::HandleNode(CResource& Loader, CXMLNode& Node, CElement* pParen } else { - pNode = m_pGroups->CreateFromXML(pParent, Node, m_pEvents); + pNode = m_pGroups->CreateFromXML(pParent, Node); } // Set the node we created in the pointer we were given diff --git a/Server/mods/deathmatch/logic/CMapManager.h b/Server/mods/deathmatch/logic/CMapManager.h index 3ab5616cddd..6aec7fe16ab 100644 --- a/Server/mods/deathmatch/logic/CMapManager.h +++ b/Server/mods/deathmatch/logic/CMapManager.h @@ -33,7 +33,7 @@ class CMapManager CMapManager(CBlipManager* pBlipManager, CObjectManager* pObjectManager, CPickupManager* pPickupManager, CPlayerManager* pPlayerManager, CRadarAreaManager* pRadarAreaManager, CMarkerManager* pMarkerManager, CVehicleManager* pVehicleManager, CTeamManager* pTeamManager, CPedManager* pPedManager, CColManager* pColManager, CWaterManager* pWaterManager, CClock* pClock, - CGroups* pGroups, CEvents* pEvents, class CScriptDebugging* pScriptDebugging, CElementDeleter* pElementDeleter); + CGroups* pGroups, class CScriptDebugging* pScriptDebugging, CElementDeleter* pElementDeleter); ~CMapManager(); CBlendedWeather* GetWeather() { return m_pBlendedWeather; }; @@ -92,7 +92,6 @@ class CMapManager CWaterManager* m_pWaterManager; CClock* m_pServerClock; CGroups* m_pGroups; - CEvents* m_pEvents; class CScriptDebugging* m_pScriptDebugging; CElementDeleter* m_pElementDeleter; diff --git a/Server/mods/deathmatch/logic/CMarker.cpp b/Server/mods/deathmatch/logic/CMarker.cpp index afdda4919a2..2c9dce9e1ba 100644 --- a/Server/mods/deathmatch/logic/CMarker.cpp +++ b/Server/mods/deathmatch/logic/CMarker.cpp @@ -304,14 +304,14 @@ void CMarker::Callback_OnCollision(CColShape& Shape, CElement& Element) CLuaArguments Arguments; Arguments.PushElement(&Element); // Hit element Arguments.PushBoolean(GetDimension() == Element.GetDimension()); // Matching dimension? - CallEvent("onMarkerHit", Arguments); + CallEvent(BuiltInEvents::onMarkerHit, Arguments); if (IS_PLAYER(&Element)) { CLuaArguments Arguments2; Arguments2.PushElement(this); // marker Arguments2.PushBoolean(GetDimension() == Element.GetDimension()); // Matching dimension? - Element.CallEvent("onPlayerMarkerHit", Arguments2); + Element.CallEvent(BuiltInEvents::onPlayerMarkerHit, Arguments2); } } } @@ -325,14 +325,14 @@ void CMarker::Callback_OnLeave(CColShape& Shape, CElement& Element) CLuaArguments Arguments; Arguments.PushElement(&Element); // Hit element Arguments.PushBoolean(GetDimension() == Element.GetDimension()); // Matching dimension? - CallEvent("onMarkerLeave", Arguments); + CallEvent(BuiltInEvents::onMarkerLeave, Arguments); if (IS_PLAYER(&Element)) { CLuaArguments Arguments2; Arguments2.PushElement(this); // marker Arguments2.PushBoolean(GetDimension() == Element.GetDimension()); // Matching dimension? - Element.CallEvent("onPlayerMarkerLeave", Arguments2); + Element.CallEvent(BuiltInEvents::onPlayerMarkerLeave, Arguments2); } } } diff --git a/Server/mods/deathmatch/logic/CMarker.h b/Server/mods/deathmatch/logic/CMarker.h index 345ed39a474..fa9f42cc00d 100644 --- a/Server/mods/deathmatch/logic/CMarker.h +++ b/Server/mods/deathmatch/logic/CMarker.h @@ -15,7 +15,6 @@ #include "CColCallback.h" #include "CColManager.h" #include "CColShape.h" -#include "CEvents.h" #include "CPerPlayerEntity.h" class CMarker : public CPerPlayerEntity, private CColCallback diff --git a/Server/mods/deathmatch/logic/CMarkerManager.cpp b/Server/mods/deathmatch/logic/CMarkerManager.cpp index f6de51bcda8..bb8ac422826 100644 --- a/Server/mods/deathmatch/logic/CMarkerManager.cpp +++ b/Server/mods/deathmatch/logic/CMarkerManager.cpp @@ -30,11 +30,11 @@ CMarker* CMarkerManager::Create(CElement* pParent) return pMarker; } -CMarker* CMarkerManager::CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents) +CMarker* CMarkerManager::CreateFromXML(CElement* pParent, CXMLNode& Node) { CMarker* const pMarker = new CMarker(this, m_pColManager, pParent); - if (pMarker->GetID() == INVALID_ELEMENT_ID || !pMarker->LoadFromCustomData(pEvents, Node)) + if (pMarker->GetID() == INVALID_ELEMENT_ID || !pMarker->LoadFromCustomData(Node)) { delete pMarker; return nullptr; diff --git a/Server/mods/deathmatch/logic/CMarkerManager.h b/Server/mods/deathmatch/logic/CMarkerManager.h index 2ed674d3cfb..96397baa43e 100644 --- a/Server/mods/deathmatch/logic/CMarkerManager.h +++ b/Server/mods/deathmatch/logic/CMarkerManager.h @@ -26,7 +26,7 @@ class CMarkerManager ~CMarkerManager() { DeleteAll(); }; CMarker* Create(CElement* pParent); - CMarker* CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents); + CMarker* CreateFromXML(CElement* pParent, CXMLNode& Node); void DeleteAll(); unsigned int Count() { return static_cast(m_Markers.size()); }; diff --git a/Server/mods/deathmatch/logic/CObject.h b/Server/mods/deathmatch/logic/CObject.h index ea170408c40..58e95a56fab 100644 --- a/Server/mods/deathmatch/logic/CObject.h +++ b/Server/mods/deathmatch/logic/CObject.h @@ -12,7 +12,6 @@ // Kayl: There is now too many includes here, try to make it work with StdInc.h if possible #include "CElement.h" -#include "CEvents.h" #include "CObjectManager.h" #include "CEasingCurve.h" diff --git a/Server/mods/deathmatch/logic/CObjectManager.cpp b/Server/mods/deathmatch/logic/CObjectManager.cpp index 75f82472598..3eb6a4a46e7 100644 --- a/Server/mods/deathmatch/logic/CObjectManager.cpp +++ b/Server/mods/deathmatch/logic/CObjectManager.cpp @@ -105,11 +105,11 @@ CObject* CObjectManager::Create(CElement* pParent, bool bIsLowLod) return pObject; } -CObject* CObjectManager::CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents, bool bIsLowLod) +CObject* CObjectManager::CreateFromXML(CElement* pParent, CXMLNode& Node, bool bIsLowLod) { CObject* const pObject = new CObject(pParent, this, bIsLowLod); - if (pObject->GetID() == INVALID_ELEMENT_ID || !pObject->LoadFromCustomData(pEvents, Node)) + if (pObject->GetID() == INVALID_ELEMENT_ID || !pObject->LoadFromCustomData(Node)) { delete pObject; return nullptr; diff --git a/Server/mods/deathmatch/logic/CObjectManager.h b/Server/mods/deathmatch/logic/CObjectManager.h index 1f975cf26fc..d8a8b0f712a 100644 --- a/Server/mods/deathmatch/logic/CObjectManager.h +++ b/Server/mods/deathmatch/logic/CObjectManager.h @@ -28,7 +28,7 @@ class CObjectManager ~CObjectManager(); CObject* Create(CElement* pParent, bool bIsLowLod); - CObject* CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents, bool bIsLowLod); + CObject* CreateFromXML(CElement* pParent, CXMLNode& Node, bool bIsLowLod); void DeleteAll(); unsigned int Count() { return static_cast(m_List.size()); }; diff --git a/Server/mods/deathmatch/logic/CObjectSync.cpp b/Server/mods/deathmatch/logic/CObjectSync.cpp index 75604d85e7d..d381483882f 100644 --- a/Server/mods/deathmatch/logic/CObjectSync.cpp +++ b/Server/mods/deathmatch/logic/CObjectSync.cpp @@ -131,7 +131,7 @@ void CObjectSync::StartSync(CPlayer* pPlayer, CObject* pObject) // Call the onElementStartSync event CLuaArguments Arguments; Arguments.PushElement(pPlayer); // New syncer - pObject->CallEvent("onElementStartSync", Arguments); + pObject->CallEvent(BuiltInEvents::onElementStartSync, Arguments); } void CObjectSync::StopSync(CObject* pObject) @@ -146,7 +146,7 @@ void CObjectSync::StopSync(CObject* pObject) // Call the onElementStopSync event CLuaArguments Arguments; Arguments.PushElement(pSyncer); // Old syncer - pObject->CallEvent("onElementStopSync", Arguments); + pObject->CallEvent(BuiltInEvents::onElementStopSync, Arguments); } CPlayer* CObjectSync::FindPlayerCloseToObject(CObject* pObject, float fMaxDistance) diff --git a/Server/mods/deathmatch/logic/CPedManager.cpp b/Server/mods/deathmatch/logic/CPedManager.cpp index e66c9144fb2..e377ca9e46d 100644 --- a/Server/mods/deathmatch/logic/CPedManager.cpp +++ b/Server/mods/deathmatch/logic/CPedManager.cpp @@ -33,11 +33,11 @@ CPed* CPedManager::Create(unsigned short usModel, CElement* pParent) return pPed; } -CPed* CPedManager::CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents) +CPed* CPedManager::CreateFromXML(CElement* pParent, CXMLNode& Node) { CPed* const pPed = new CPed(this, pParent, 400); - if (pPed->GetID() == INVALID_ELEMENT_ID || !pPed->LoadFromCustomData(pEvents, Node)) + if (pPed->GetID() == INVALID_ELEMENT_ID || !pPed->LoadFromCustomData(Node)) { delete pPed; return nullptr; diff --git a/Server/mods/deathmatch/logic/CPedManager.h b/Server/mods/deathmatch/logic/CPedManager.h index 8d9a22d3d61..97b430ab399 100644 --- a/Server/mods/deathmatch/logic/CPedManager.h +++ b/Server/mods/deathmatch/logic/CPedManager.h @@ -22,7 +22,7 @@ class CPedManager ~CPedManager(); class CPed* Create(unsigned short usModel, CElement* pParent); - class CPed* CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents); + class CPed* CreateFromXML(CElement* pParent, CXMLNode& Node); void DeleteAll(); unsigned int Count() { return static_cast(m_List.size()); }; diff --git a/Server/mods/deathmatch/logic/CPedSync.cpp b/Server/mods/deathmatch/logic/CPedSync.cpp index 490a137de44..59d84749f32 100644 --- a/Server/mods/deathmatch/logic/CPedSync.cpp +++ b/Server/mods/deathmatch/logic/CPedSync.cpp @@ -10,6 +10,7 @@ *****************************************************************************/ #include "StdInc.h" +#include CPedSync::CPedSync(CPlayerManager* pPlayerManager, CPedManager* pPedManager) { @@ -134,7 +135,7 @@ void CPedSync::StartSync(CPlayer* pPlayer, CPed* pPed) // Call the onElementStartSync event CLuaArguments Arguments; Arguments.PushElement(pPlayer); // New syncer - pPed->CallEvent("onElementStartSync", Arguments); + pPed->CallEvent(BuiltInEvents::onElementStartSync, Arguments); } void CPedSync::StopSync(CPed* pPed) @@ -149,7 +150,7 @@ void CPedSync::StopSync(CPed* pPed) // Call the onElementStopSync event CLuaArguments Arguments; Arguments.PushElement(pSyncer); // Old syncer - pPed->CallEvent("onElementStopSync", Arguments); + pPed->CallEvent(BuiltInEvents::onElementStopSync, Arguments); } CPlayer* CPedSync::FindPlayerCloseToPed(CPed* pPed, float fMaxDistance) @@ -234,10 +235,15 @@ void CPedSync::Packet_PedSync(CPedSyncPacket& Packet) if (fDeltaHealth > 0.0f) { - // Call the onPedDamage event - CLuaArguments Arguments; - Arguments.PushNumber(fDeltaHealth); - pPed->CallEvent("onPedDamage", Arguments); + // This event wasn't registered as built-in for whatever reason + // But we must keep it, as people might've discovered it (and registered it with addEvent) + if (auto* event = CustomEvent::Get("onPedDamage")) + { + // Call the onPedDamage event + CLuaArguments Arguments; + Arguments.PushNumber(fDeltaHealth); + pPed->CallEvent(*event, Arguments); // + } } } } diff --git a/Server/mods/deathmatch/logic/CPerfStat.LuaTiming.cpp b/Server/mods/deathmatch/logic/CPerfStat.LuaTiming.cpp index 496c078982c..b699350daad 100644 --- a/Server/mods/deathmatch/logic/CPerfStat.LuaTiming.cpp +++ b/Server/mods/deathmatch/logic/CPerfStat.LuaTiming.cpp @@ -124,7 +124,7 @@ class CPerfStatLuaTimingImpl : public CPerfStatLuaTiming // CPerfStatLuaTiming virtual void OnLuaMainCreate(CLuaMain* pLuaMain); virtual void OnLuaMainDestroy(CLuaMain* pLuaMain); - virtual void UpdateLuaTiming(CLuaMain* pLuaMain, const char* szEventName, TIMEUS timeUs); + virtual void UpdateLuaTiming(CLuaMain* pLuaMain, const std::string& eventName, TIMEUS timeUs); // CPerfStatLuaTimingImpl functions void GetLuaTimingStats(CPerfStatResult* pResult, const std::map& strOptionMap, const SString& strFilter); @@ -220,29 +220,19 @@ void CPerfStatLuaTimingImpl::OnLuaMainDestroy(CLuaMain* pLuaMain) // // /////////////////////////////////////////////////////////////// -void CPerfStatLuaTimingImpl::UpdateLuaTiming(CLuaMain* pLuaMain, const char* szEventName, TIMEUS timeUs) +void CPerfStatLuaTimingImpl::UpdateLuaTiming(CLuaMain* pLuaMain, const std::string& eventName, TIMEUS timeUs) { - CLuaMainTiming* pLuaMainTiming = MapFind(AllLuaTiming.LuaMainTimingMap, pLuaMain); - if (!pLuaMainTiming) - { - MapSet(AllLuaTiming.LuaMainTimingMap, pLuaMain, CLuaMainTiming()); - pLuaMainTiming = MapFind(AllLuaTiming.LuaMainTimingMap, pLuaMain); - } + CLuaMainTiming& luaMainTiming = AllLuaTiming.LuaMainTimingMap[pLuaMain]; + // Resource { - CTiming& acc = pLuaMainTiming->ResourceTiming.s5.acc; + CTiming& acc = luaMainTiming.ResourceTiming.s5.acc; acc.total_us += timeUs; } - CTimingBlock* pEventTiming = MapFind(pLuaMainTiming->EventTimingMap, szEventName); - if (!pEventTiming) - { - MapSet(pLuaMainTiming->EventTimingMap, szEventName, CTimingBlock()); - pEventTiming = MapFind(pLuaMainTiming->EventTimingMap, szEventName); - } - + // This event { - CTiming& acc = pEventTiming->s5.acc; + CTiming& acc = luaMainTiming.EventTimingMap[eventName].s5.acc; acc.calls++; acc.total_us += timeUs; acc.max_us = std::max(acc.max_us, timeUs); diff --git a/Server/mods/deathmatch/logic/CPerfStatModule.h b/Server/mods/deathmatch/logic/CPerfStatModule.h index da6117748b8..345710b1199 100644 --- a/Server/mods/deathmatch/logic/CPerfStatModule.h +++ b/Server/mods/deathmatch/logic/CPerfStatModule.h @@ -130,7 +130,7 @@ class CPerfStatLuaTiming : public CPerfStatModule // CPerfStatLuaTiming virtual void OnLuaMainCreate(CLuaMain* pLuaMain) = 0; virtual void OnLuaMainDestroy(CLuaMain* pLuaMain) = 0; - virtual void UpdateLuaTiming(CLuaMain* pLuaMain, const char* szEventName, TIMEUS timeUs) = 0; + virtual void UpdateLuaTiming(CLuaMain* pLuaMain, const std::string& eventName, TIMEUS timeUs) = 0; static CPerfStatLuaTiming* GetSingleton(); }; diff --git a/Server/mods/deathmatch/logic/CPickup.cpp b/Server/mods/deathmatch/logic/CPickup.cpp index 89ac012231a..2d5afb60091 100644 --- a/Server/mods/deathmatch/logic/CPickup.cpp +++ b/Server/mods/deathmatch/logic/CPickup.cpp @@ -396,17 +396,17 @@ void CPickup::Use(CPlayer& Player) // Call the onPickupUse event CLuaArguments Arguments; Arguments.PushElement(&Player); - if (!CallEvent("onPickupUse", Arguments)) + if (!CallEvent(BuiltInEvents::onPickupUse, Arguments)) { CLuaArguments Arguments2; Arguments2.PushElement(this); // pickup - Player.CallEvent("onPlayerPickupUse", Arguments2); + Player.CallEvent(BuiltInEvents::onPlayerPickupUse, Arguments2); } else { CLuaArguments Arguments2; Arguments2.PushElement(this); // pickup - if (Player.CallEvent("onPlayerPickupUse", Arguments2)) + if (Player.CallEvent(BuiltInEvents::onPlayerPickupUse, Arguments2)) { // Tell all the other players to hide it if the respawn intervals are bigger than 0 if (m_ulRespawnIntervals > 0) @@ -487,11 +487,11 @@ void CPickup::Callback_OnCollision(CColShape& Shape, CElement& Element) // Call the onPickupHit event CLuaArguments Arguments; Arguments.PushElement(&Player); - bool bContinue1 = CallEvent("onPickupHit", Arguments); + bool bContinue1 = CallEvent(BuiltInEvents::onPickupHit, Arguments); CLuaArguments Arguments2; Arguments2.PushElement(this); // pickup - bool bContinue2 = Element.CallEvent("onPlayerPickupHit", Arguments2); + bool bContinue2 = Element.CallEvent(BuiltInEvents::onPlayerPickupHit, Arguments2); if (bContinue1 && bContinue2) { @@ -530,11 +530,11 @@ void CPickup::Callback_OnLeave(CColShape& Shape, CElement& Element) // Call the onPickupLeave event CLuaArguments Arguments; Arguments.PushElement(&Player); - CallEvent("onPickupLeave", Arguments); + CallEvent(BuiltInEvents::onPickupLeave, Arguments); CLuaArguments Arguments2; Arguments2.PushElement(this); // pickup - Element.CallEvent("onPlayerPickupLeave", Arguments2); + Element.CallEvent(BuiltInEvents::onPlayerPickupLeave, Arguments2); } } } diff --git a/Server/mods/deathmatch/logic/CPickup.h b/Server/mods/deathmatch/logic/CPickup.h index 72ea8cf9754..a20752fbe15 100644 --- a/Server/mods/deathmatch/logic/CPickup.h +++ b/Server/mods/deathmatch/logic/CPickup.h @@ -17,7 +17,6 @@ class CPickup; #include "CColManager.h" #include "CColSphere.h" #include "CElement.h" -#include "CEvents.h" class CPickup final : public CElement, private CColCallback { diff --git a/Server/mods/deathmatch/logic/CPickupManager.cpp b/Server/mods/deathmatch/logic/CPickupManager.cpp index 1d3a544416a..c0dfdf98dd2 100644 --- a/Server/mods/deathmatch/logic/CPickupManager.cpp +++ b/Server/mods/deathmatch/logic/CPickupManager.cpp @@ -38,11 +38,11 @@ CPickup* CPickupManager::Create(CElement* pParent) return pPickup; } -CPickup* CPickupManager::CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents) +CPickup* CPickupManager::CreateFromXML(CElement* pParent, CXMLNode& Node) { CPickup* const pPickup = new CPickup(pParent, this, m_pColManager); - if (pPickup->GetID() == INVALID_ELEMENT_ID || !pPickup->LoadFromCustomData(pEvents, Node)) + if (pPickup->GetID() == INVALID_ELEMENT_ID || !pPickup->LoadFromCustomData(Node)) { delete pPickup; return nullptr; diff --git a/Server/mods/deathmatch/logic/CPickupManager.h b/Server/mods/deathmatch/logic/CPickupManager.h index f7398352683..98bcb0d8148 100644 --- a/Server/mods/deathmatch/logic/CPickupManager.h +++ b/Server/mods/deathmatch/logic/CPickupManager.h @@ -26,7 +26,7 @@ class CPickupManager ~CPickupManager() { DeleteAll(); }; CPickup* Create(CElement* pParent); - CPickup* CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents); + CPickup* CreateFromXML(CElement* pParent, CXMLNode& Node); void DeleteAll(); unsigned int Count() { return static_cast(m_List.size()); }; diff --git a/Server/mods/deathmatch/logic/CPlayer.cpp b/Server/mods/deathmatch/logic/CPlayer.cpp index fd27c72bfec..f4ed8c6c281 100644 --- a/Server/mods/deathmatch/logic/CPlayer.cpp +++ b/Server/mods/deathmatch/logic/CPlayer.cpp @@ -357,7 +357,7 @@ void CPlayer::RemoveAllSyncingVehicles() CLuaArguments Arguments; Arguments.PushElement(this); - (*iter)->CallEvent("onElementStopSync", Arguments); + (*iter)->CallEvent(BuiltInEvents::onElementStopSync, Arguments); } } @@ -403,7 +403,7 @@ void CPlayer::RemoveAllSyncingPeds() CLuaArguments Arguments; Arguments.PushElement(this); - (*iter)->CallEvent("onElementStopSync", Arguments); + (*iter)->CallEvent(BuiltInEvents::onElementStopSync, Arguments); } } @@ -449,7 +449,7 @@ void CPlayer::RemoveAllSyncingObjects() CLuaArguments Arguments; Arguments.PushElement(this); - (*iter)->CallEvent("onElementStopSync", Arguments); + (*iter)->CallEvent(BuiltInEvents::onElementStopSync, Arguments); } } diff --git a/Server/mods/deathmatch/logic/CRPCFunctions.cpp b/Server/mods/deathmatch/logic/CRPCFunctions.cpp index f43deae070d..0e343b98815 100644 --- a/Server/mods/deathmatch/logic/CRPCFunctions.cpp +++ b/Server/mods/deathmatch/logic/CRPCFunctions.cpp @@ -134,7 +134,7 @@ void CRPCFunctions::PlayerTarget(NetBitStreamInterface& bitStream) else Arguments.PushBoolean(false); - m_pSourcePlayer->CallEvent("onPlayerTarget", Arguments); + m_pSourcePlayer->CallEvent(BuiltInEvents::onPlayerTarget, Arguments); } UNCLOCK("NetServerPulse::RPC", "PlayerTarget"); } @@ -168,7 +168,7 @@ void CRPCFunctions::PlayerWeapon(NetBitStreamInterface& bitStream) Arguments.PushNumber(m_pSourcePlayer->GetWeaponType(ucPrevSlot)); Arguments.PushNumber(m_pSourcePlayer->GetWeaponType(uiSlot)); - m_pSourcePlayer->CallEvent("onPlayerWeaponSwitch", Arguments); + m_pSourcePlayer->CallEvent(BuiltInEvents::onPlayerWeaponSwitch, Arguments); } m_pSourcePlayer->SetWeaponSlot(uiSlot); @@ -286,7 +286,7 @@ void CRPCFunctions::CursorEvent(NetBitStreamInterface& bitStream) Arguments.PushNumber(vecPosition.fX); Arguments.PushNumber(vecPosition.fY); Arguments.PushNumber(vecPosition.fZ); - pElement->CallEvent("onElementClicked", Arguments); + pElement->CallEvent(BuiltInEvents::onElementClicked, Arguments); } // Call the onPlayerClick event CLuaArguments Arguments; @@ -301,7 +301,7 @@ void CRPCFunctions::CursorEvent(NetBitStreamInterface& bitStream) Arguments.PushNumber(vecPosition.fZ); Arguments.PushNumber(vecCursorPosition.fX); Arguments.PushNumber(vecCursorPosition.fY); - m_pSourcePlayer->CallEvent("onPlayerClick", Arguments); + m_pSourcePlayer->CallEvent(BuiltInEvents::onPlayerClick, Arguments); // TODO: iterate server-side element managers for the click events, eg: colshapes } @@ -334,7 +334,7 @@ void CRPCFunctions::RequestStealthKill(NetBitStreamInterface& bitStream) { CLuaArguments Arguments; Arguments.PushElement(pTarget); - if (m_pSourcePlayer->CallEvent("onPlayerStealthKill", Arguments)) + if (m_pSourcePlayer->CallEvent(BuiltInEvents::onPlayerStealthKill, Arguments)) { // Start the stealth kill CStaticFunctionDefinitions::KillPed(pTarget, m_pSourcePlayer, 4 /*WEAPONTYPE_KNIFE*/, 9 /*BODYPART_HEAD*/, true); diff --git a/Server/mods/deathmatch/logic/CRadarAreaManager.cpp b/Server/mods/deathmatch/logic/CRadarAreaManager.cpp index 5f7bebc1095..5fecc132cc4 100644 --- a/Server/mods/deathmatch/logic/CRadarAreaManager.cpp +++ b/Server/mods/deathmatch/logic/CRadarAreaManager.cpp @@ -34,11 +34,11 @@ CRadarArea* CRadarAreaManager::Create(CElement* pParent) return pArea; } -CRadarArea* CRadarAreaManager::CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents) +CRadarArea* CRadarAreaManager::CreateFromXML(CElement* pParent, CXMLNode& Node) { CRadarArea* const pArea = new CRadarArea(this, pParent); - if (pArea->GetID() == INVALID_ELEMENT_ID || !pArea->LoadFromCustomData(pEvents, Node)) + if (pArea->GetID() == INVALID_ELEMENT_ID || !pArea->LoadFromCustomData(Node)) { delete pArea; return nullptr; diff --git a/Server/mods/deathmatch/logic/CRadarAreaManager.h b/Server/mods/deathmatch/logic/CRadarAreaManager.h index bbf2536a340..8b53b7a8085 100644 --- a/Server/mods/deathmatch/logic/CRadarAreaManager.h +++ b/Server/mods/deathmatch/logic/CRadarAreaManager.h @@ -23,7 +23,7 @@ class CRadarAreaManager ~CRadarAreaManager(); CRadarArea* Create(CElement* pParent); - CRadarArea* CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents); + CRadarArea* CreateFromXML(CElement* pParent, CXMLNode& Node); void DeleteAll(); unsigned int Count() { return static_cast(m_List.size()); }; diff --git a/Server/mods/deathmatch/logic/CResource.cpp b/Server/mods/deathmatch/logic/CResource.cpp index 2df06835e67..92e8a09bc08 100644 --- a/Server/mods/deathmatch/logic/CResource.cpp +++ b/Server/mods/deathmatch/logic/CResource.cpp @@ -723,7 +723,7 @@ bool CResource::Start(std::list* pDependents, bool bManualStart, con CLuaArguments PreStartArguments; PreStartArguments.PushResource(this); - if (!g_pGame->GetMapManager()->GetRootElement()->CallEvent("onResourcePreStart", PreStartArguments)) + if (!g_pGame->GetMapManager()->GetRootElement()->CallEvent(BuiltInEvents::onResourcePreStart, PreStartArguments)) { // Start cancelled by another resource m_strFailureReason = "Start cancelled by script\n"; @@ -957,7 +957,7 @@ bool CResource::Start(std::list* pDependents, bool bManualStart, con CLuaArguments Arguments; Arguments.PushResource(this); - if (!m_pResourceElement->CallEvent("onResourceStart", Arguments)) + if (!m_pResourceElement->CallEvent(BuiltInEvents::onResourceStart, Arguments)) { // We're no longer active. stop the resource CLogger::LogPrintf("Start up of resource %s cancelled by script\n", m_strResourceName.c_str()); @@ -1025,7 +1025,7 @@ bool CResource::Stop(bool bManualStop) CLuaArguments Arguments; Arguments.PushResource(this); Arguments.PushBoolean(m_bDestroyed); - m_pResourceElement->CallEvent("onResourceStop", Arguments); + m_pResourceElement->CallEvent(BuiltInEvents::onResourceStop, Arguments); // Remove us from the resources we depend on (they might unload too first) for (CIncludedResources* pIncludedResources : m_IncludedResources) diff --git a/Server/mods/deathmatch/logic/CResourceManager.cpp b/Server/mods/deathmatch/logic/CResourceManager.cpp index 801fbe6081b..66f99589f97 100644 --- a/Server/mods/deathmatch/logic/CResourceManager.cpp +++ b/Server/mods/deathmatch/logic/CResourceManager.cpp @@ -275,7 +275,7 @@ void CResourceManager::OnResourceLoadStateChange(CResource* pResource, const cha else Arguments.PushNil(); - g_pGame->GetMapManager()->GetRootElement()->CallEvent("onResourceLoadStateChange", Arguments); + g_pGame->GetMapManager()->GetRootElement()->CallEvent(BuiltInEvents::onResourceLoadStateChange, Arguments); } const char* CResourceManager::GetResourceDirectory() diff --git a/Server/mods/deathmatch/logic/CResourceMapItem.cpp b/Server/mods/deathmatch/logic/CResourceMapItem.cpp index 7079e4f2f61..6c6a4c9e38e 100644 --- a/Server/mods/deathmatch/logic/CResourceMapItem.cpp +++ b/Server/mods/deathmatch/logic/CResourceMapItem.cpp @@ -27,7 +27,6 @@ CResourceMapItem::CResourceMapItem(CResource* pResource, const char* szShortName m_pTeamManager = g_pGame->GetTeamManager(); m_pPedManager = g_pGame->GetPedManager(); m_pWaterManager = g_pGame->GetWaterManager(); - m_pEvents = g_pGame->GetEvents(); m_pElementGroup = nullptr; m_iDimension = iDimension; m_type = RESOURCE_FILE_TYPE_MAP; @@ -131,52 +130,52 @@ void CResourceMapItem::HandleNode(CXMLNode& Node, CElement* pParent) { case CElement::VEHICLE: { - pNode = m_pVehicleManager->CreateFromXML(pParent, Node, m_pEvents); + pNode = m_pVehicleManager->CreateFromXML(pParent, Node); break; } case CElement::OBJECT: { - pNode = m_pObjectManager->CreateFromXML(pParent, Node, m_pEvents, false); + pNode = m_pObjectManager->CreateFromXML(pParent, Node, false); break; } case CElement::BLIP: { - pNode = m_pBlipManager->CreateFromXML(pParent, Node, m_pEvents); + pNode = m_pBlipManager->CreateFromXML(pParent, Node); break; } case CElement::PICKUP: { - pNode = m_pPickupManager->CreateFromXML(pParent, Node, m_pEvents); + pNode = m_pPickupManager->CreateFromXML(pParent, Node); break; } case CElement::MARKER: { - pNode = m_pMarkerManager->CreateFromXML(pParent, Node, m_pEvents); + pNode = m_pMarkerManager->CreateFromXML(pParent, Node); break; } case CElement::RADAR_AREA: { - pNode = m_pRadarAreaManager->CreateFromXML(pParent, Node, m_pEvents); + pNode = m_pRadarAreaManager->CreateFromXML(pParent, Node); break; } case CElement::TEAM: { - pNode = m_pTeamManager->CreateFromXML(pParent, Node, m_pEvents); + pNode = m_pTeamManager->CreateFromXML(pParent, Node); break; } case CElement::PED: { - pNode = m_pPedManager->CreateFromXML(pParent, Node, m_pEvents); + pNode = m_pPedManager->CreateFromXML(pParent, Node); break; } case CElement::WATER: { - pNode = m_pWaterManager->CreateFromXML(pParent, Node, m_pEvents); + pNode = m_pWaterManager->CreateFromXML(pParent, Node); break; } default: { - pNode = m_pGroups->CreateFromXML(pParent, Node, m_pEvents); + pNode = m_pGroups->CreateFromXML(pParent, Node); break; } } diff --git a/Server/mods/deathmatch/logic/CResourceMapItem.h b/Server/mods/deathmatch/logic/CResourceMapItem.h index 823ca008d08..27678287849 100644 --- a/Server/mods/deathmatch/logic/CResourceMapItem.h +++ b/Server/mods/deathmatch/logic/CResourceMapItem.h @@ -29,7 +29,6 @@ class CVehicleManager; class CTeamManager; class CPedManager; class CWaterManager; -class CEvents; // This class represents a single resource map item, being a .map file // It's task is to load the .map file into elements and store them @@ -65,7 +64,6 @@ class CResourceMapItem : public CResourceFile CTeamManager* m_pTeamManager; CPedManager* m_pPedManager; CWaterManager* m_pWaterManager; - CEvents* m_pEvents; CDummy* m_pMapElement; CElementGroup* m_pElementGroup; int m_iDimension; diff --git a/Server/mods/deathmatch/logic/CSettings.cpp b/Server/mods/deathmatch/logic/CSettings.cpp index 57f0ee3a8de..21b91c62cc4 100644 --- a/Server/mods/deathmatch/logic/CSettings.cpp +++ b/Server/mods/deathmatch/logic/CSettings.cpp @@ -370,7 +370,7 @@ bool CSettings::Set(const char* szLocalResource, const char* szSetting, const ch Arguments.PushString(szContent); - g_pGame->GetMapManager()->GetRootElement()->CallEvent("onSettingChange", Arguments); + g_pGame->GetMapManager()->GetRootElement()->CallEvent(BuiltInEvents::onSettingChange, Arguments); // Save the XML file if (m_pFile->Write()) diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index fe6ed2a7b9f..cf82f545811 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -25,7 +25,6 @@ static CBlipManager* m_pBlipManager; static CRadarAreaManager* m_pRadarAreaManager; static CTeamManager* m_pTeamManager; static CClock* m_pClock; -static CEvents* m_pEvents; static CElementDeleter* m_pElementDeleter; static CMainConfig* m_pMainConfig; static CRegistry* m_pRegistry; @@ -61,7 +60,6 @@ CStaticFunctionDefinitions::CStaticFunctionDefinitions(CGame* pGame) m_pRadarAreaManager = pGame->GetRadarAreaManager(); m_pTeamManager = pGame->GetTeamManager(); m_pClock = pGame->GetClock(); - m_pEvents = pGame->GetEvents(); m_pElementDeleter = pGame->GetElementDeleter(); m_pMainConfig = pGame->GetConfig(); m_pRegistry = pGame->GetRegistry(); @@ -76,72 +74,6 @@ CStaticFunctionDefinitions::~CStaticFunctionDefinitions() { } -bool CStaticFunctionDefinitions::AddEvent(CLuaMain* pLuaMain, const char* szName, const char* szArguments, bool bAllowRemoteTrigger) -{ - assert(pLuaMain); - assert(szName); - assert(szArguments); - - // Valid name? - if (strlen(szName) > 0) - { - // Add our event to CEvents - return m_pEvents->AddEvent(szName, szArguments, pLuaMain, bAllowRemoteTrigger); - } - - return false; -} - -bool CStaticFunctionDefinitions::AddEventHandler(CLuaMain* pLuaMain, const char* szName, CElement* pElement, const CLuaFunctionRef& iLuaFunction, - bool bPropagated, EEventPriorityType eventPriority, float fPriorityMod) -{ - assert(pLuaMain); - assert(szName); - assert(pElement); - - // We got an event with that name? - if (m_pEvents->Exists(szName)) - { - // Add the event handler - if (pElement->AddEvent(pLuaMain, szName, iLuaFunction, bPropagated, eventPriority, fPriorityMod)) - return true; - } - - return false; -} - -bool CStaticFunctionDefinitions::RemoveEventHandler(CLuaMain* pLuaMain, const char* szName, CElement* pElement, const CLuaFunctionRef& iLuaFunction) -{ - assert(pLuaMain); - assert(szName); - assert(pElement); - - // We got an event and handler with that name? - if (m_pEvents->Exists(szName)) - { - if (pElement->DeleteEvent(pLuaMain, szName, iLuaFunction)) - { - return true; - } - } - - return false; -} - -bool CStaticFunctionDefinitions::TriggerEvent(const char* szName, CElement* pElement, const CLuaArguments& Arguments, bool& bWasCanceled) -{ - // There is such event? - if (m_pEvents->Exists(szName)) - { - // Call the event - pElement->CallEvent(szName, Arguments); - bWasCanceled = m_pEvents->WasEventCancelled(); - return true; - } - - return false; -} - bool CStaticFunctionDefinitions::TriggerClientEvent(const std::vector& sendList, const char* szName, CElement* pCallWithElement, CLuaArguments& Arguments) { @@ -179,22 +111,6 @@ bool CStaticFunctionDefinitions::TriggerLatentClientEvent(const std::vectorCancelEvent(bCancel, szReason); - return true; -} - -const char* CStaticFunctionDefinitions::GetCancelReason() -{ - return m_pEvents->GetLastError(); -} - -bool CStaticFunctionDefinitions::WasEventCancelled() -{ - return m_pEvents->WasEventCancelled(); -} - CDummy* CStaticFunctionDefinitions::CreateElement(CResource* pResource, const char* szTypeName, const char* szID) { assert(szTypeName); @@ -1637,7 +1553,7 @@ bool CStaticFunctionDefinitions::SetElementModel(CElement* pElement, unsigned sh Arguments.PushNumber(pPed->GetModel()); // Get the old model pPed->SetModel(usModel); // Set the new model Arguments.PushNumber(usModel); // Get the new model - pPed->CallEvent("onElementModelChange", Arguments); + pPed->CallEvent(BuiltInEvents::onElementModelChange, Arguments); break; } case CElement::VEHICLE: @@ -1651,7 +1567,7 @@ bool CStaticFunctionDefinitions::SetElementModel(CElement* pElement, unsigned sh Arguments.PushNumber(pVehicle->GetModel()); // Get the old model pVehicle->SetModel(usModel); // Set the new model Arguments.PushNumber(usModel); // Get the new model - pVehicle->CallEvent("onElementModelChange", Arguments); + pVehicle->CallEvent(BuiltInEvents::onElementModelChange, Arguments); // Check for any passengers above the max seat list unsigned char ucMaxPassengers = pVehicle->GetMaxPassengers(); @@ -1682,7 +1598,7 @@ bool CStaticFunctionDefinitions::SetElementModel(CElement* pElement, unsigned sh Arguments.PushNumber(pObject->GetModel()); // Get the old model pObject->SetModel(usModel); // Set the new model Arguments.PushNumber(usModel); // Get the new model - pObject->CallEvent("onElementModelChange", Arguments); + pObject->CallEvent(BuiltInEvents::onElementModelChange, Arguments); break; } default: @@ -1948,7 +1864,7 @@ bool CStaticFunctionDefinitions::SetPlayerName(CElement* pElement, const char* s Arguments.PushString(szNick); Arguments.PushString(szName); Arguments.PushBoolean(false); // manually changed - pPlayer->CallEvent("onPlayerChangeNick", Arguments); + pPlayer->CallEvent(BuiltInEvents::onPlayerChangeNick, Arguments); // Tell the console CLogger::LogPrintf("NICK: %s is now known as %s\n", szNick, szName); @@ -3310,9 +3226,9 @@ bool CStaticFunctionDefinitions::SetPlayerMuted(CElement* pElement, bool bMuted) CLuaArguments arguments; if (bMuted) - bEventCancelled = !pPlayer->CallEvent("onPlayerMute", arguments); + bEventCancelled = !pPlayer->CallEvent(BuiltInEvents::onPlayerMute, arguments); else - bEventCancelled = !pPlayer->CallEvent("onPlayerUnmute", arguments); + bEventCancelled = !pPlayer->CallEvent(BuiltInEvents::onPlayerUnmute, arguments); if (!bEventCancelled) { @@ -3664,14 +3580,14 @@ bool CStaticFunctionDefinitions::KillPed(CElement* pElement, CElement* pKiller, // Tell everyone to kill this player CPlayerWastedPacket WastedPacket(pPed, pKiller, ucKillerWeapon, ucBodyPart, bStealth); m_pPlayerManager->BroadcastOnlyJoined(WastedPacket); - pPed->CallEvent("onPlayerWasted", Arguments); + pPed->CallEvent(BuiltInEvents::onPlayerWasted, Arguments); } else { // Tell everyone to kill this player CPedWastedPacket WastedPacket(pPed, pKiller, ucKillerWeapon, ucBodyPart, bStealth); m_pPlayerManager->BroadcastOnlyJoined(WastedPacket); - pPed->CallEvent("onPedWasted", Arguments); + pPed->CallEvent(BuiltInEvents::onPedWasted, Arguments); } for (unsigned int slot = 0; slot < WEAPON_SLOTS; ++slot) @@ -4121,9 +4037,9 @@ bool CStaticFunctionDefinitions::WarpPedIntoVehicle(CPed* pPed, CVehicle* pVehic PlayerVehicleArguments.PushBoolean(false); // Leave onPlayerVehicleEnter for backwards compatibility if (IS_PLAYER(pPed)) - pPed->CallEvent("onPlayerVehicleEnter", PlayerVehicleArguments); + pPed->CallEvent(BuiltInEvents::onPlayerVehicleEnter, PlayerVehicleArguments); else - pPed->CallEvent("onPedVehicleEnter", PlayerVehicleArguments); + pPed->CallEvent(BuiltInEvents::onPedVehicleEnter, PlayerVehicleArguments); // Call the vehicle->player event CLuaArguments VehiclePlayerArguments; @@ -4133,7 +4049,7 @@ bool CStaticFunctionDefinitions::WarpPedIntoVehicle(CPed* pPed, CVehicle* pVehic VehiclePlayerArguments.PushElement(pPreviousOccupant); else VehiclePlayerArguments.PushBoolean(false); - pVehicle->CallEvent("onVehicleEnter", VehiclePlayerArguments); + pVehicle->CallEvent(BuiltInEvents::onVehicleEnter, VehiclePlayerArguments); // Used to check if f.e. lua changed the player's vehicle (fix for #7570) pVehicle->m_bOccupantChanged = true; @@ -4168,9 +4084,9 @@ bool CStaticFunctionDefinitions::RemovePedFromVehicle(CElement* pElement) Arguments.PushBoolean(false); // jacker Arguments.PushBoolean(true); // forcedByScript if (IS_PLAYER(pPed)) - pPed->CallEvent("onPlayerVehicleExit", Arguments); + pPed->CallEvent(BuiltInEvents::onPlayerVehicleExit, Arguments); else - pPed->CallEvent("onPedVehicleExit", Arguments); + pPed->CallEvent(BuiltInEvents::onPedVehicleExit, Arguments); // Call the vehicle->ped event CLuaArguments Arguments2; @@ -4178,7 +4094,7 @@ bool CStaticFunctionDefinitions::RemovePedFromVehicle(CElement* pElement) Arguments2.PushNumber(ucOccupiedSeat); // seat Arguments2.PushBoolean(false); // jacker Arguments2.PushBoolean(true); // forcedByScript - pVehicle->CallEvent("onVehicleExit", Arguments2); + pVehicle->CallEvent(BuiltInEvents::onVehicleExit, Arguments2); // Remove him from the vehicle pVehicle->SetOccupant(NULL, ucOccupiedSeat); @@ -4594,9 +4510,9 @@ bool CStaticFunctionDefinitions::GiveWeapon(CElement* pElement, unsigned char uc Arguments.PushNumber(ucWeaponID); bool bEventRet; if (IS_PLAYER(pElement)) - bEventRet = pPed->CallEvent("onPlayerWeaponSwitch", Arguments); + bEventRet = pPed->CallEvent(BuiltInEvents::onPlayerWeaponSwitch, Arguments); else - bEventRet = pPed->CallEvent("onPedWeaponSwitch", Arguments); + bEventRet = pPed->CallEvent(BuiltInEvents::onPedWeaponSwitch, Arguments); if (!bEventRet) bSetAsCurrent = false; @@ -5285,7 +5201,7 @@ bool CStaticFunctionDefinitions::BlowVehicle(CElement* pElement) vehicle->SetIsBlown(true); CLuaArguments Arguments; - vehicle->CallEvent("onVehicleExplode", Arguments); + vehicle->CallEvent(BuiltInEvents::onVehicleExplode, Arguments); // Abort if vehicle got fixed or destroyed if (!vehicle->GetIsBlown() || vehicle->IsBeingDeleted()) @@ -6820,7 +6736,7 @@ bool CStaticFunctionDefinitions::RespawnVehicle(CElement* pElement) // Call the respawn event? CLuaArguments Arguments; Arguments.PushBoolean(false); - pVehicle->CallEvent("onVehicleRespawn", Arguments); + pVehicle->CallEvent(BuiltInEvents::onVehicleRespawn, Arguments); // Tell everyone to respawn it CVehicleSpawnPacket Packet; @@ -6896,7 +6812,7 @@ bool CStaticFunctionDefinitions::AttachTrailerToVehicle(CVehicle* pVehicle, CVeh // Execute the attach trailer script function CLuaArguments Arguments; Arguments.PushElement(pVehicle); - bool bContinue = pTrailer->CallEvent("onTrailerAttach", Arguments); + bool bContinue = pTrailer->CallEvent(BuiltInEvents::onTrailerAttach, Arguments); if (!bContinue) { @@ -6936,7 +6852,7 @@ bool CStaticFunctionDefinitions::DetachTrailerFromVehicle(CVehicle* pVehicle, CV // Execute the detach trailer script function CLuaArguments Arguments; Arguments.PushElement(pVehicle); - pTempTrailer->CallEvent("onTrailerDetach", Arguments); + pTempTrailer->CallEvent(BuiltInEvents::onTrailerDetach, Arguments); return true; } @@ -9602,7 +9518,7 @@ bool CStaticFunctionDefinitions::FireWeapon(CCustomWeapon* pWeapon) CLuaArguments Arguments; Arguments.PushElement(NULL); - if (pWeapon->CallEvent("onWeaponFire", Arguments)) + if (pWeapon->CallEvent(BuiltInEvents::onWeaponFire, Arguments)) { CBitStream BitStream; @@ -10048,7 +9964,7 @@ bool CStaticFunctionDefinitions::OutputChatBox(const char* szText, CElement* pEl Arguments.PushString(szText); if (pResource) Arguments.PushResource(pResource); - m_pMapManager->GetRootElement()->CallEvent("onChatMessage", Arguments); + m_pMapManager->GetRootElement()->CallEvent(BuiltInEvents::onChatMessage, Arguments); } return false; @@ -11353,7 +11269,7 @@ bool CStaticFunctionDefinitions::SetAccountData(CAccount* pAccount, const char* Arguments.PushAccount(pAccount); Arguments.PushString(szKey); Arguments.PushString(strArgumentAsString); - if (m_pMapManager->GetRootElement()->CallEvent("onAccountDataChange", Arguments)) + if (m_pMapManager->GetRootElement()->CallEvent(BuiltInEvents::onAccountDataChange, Arguments)) return m_pAccountManager->SetAccountData(pAccount, szKey, strArgumentAsString, pArgument->GetType()); return false; } @@ -11483,14 +11399,14 @@ CBan* CStaticFunctionDefinitions::BanPlayer(CPlayer* pPlayer, bool bIP, bool bUs // Call the event with the responsible player as the source CLuaArguments Arguments; Arguments.PushBan(pBan); - pResponsible->CallEvent("onBan", Arguments); + pResponsible->CallEvent(BuiltInEvents::onBan, Arguments); } else { // Call the event with the root element as the source CLuaArguments Arguments; Arguments.PushBan(pBan); - m_pMapManager->GetRootElement()->CallEvent("onBan", Arguments); + m_pMapManager->GetRootElement()->CallEvent(BuiltInEvents::onBan, Arguments); } // Save the ban list @@ -11511,7 +11427,7 @@ CBan* CStaticFunctionDefinitions::BanPlayer(CPlayer* pPlayer, bool bIP, bool bUs // show him the 'kicked' message instead of our 'banned' message. const bool bLeavingServer = pPlayer->IsLeavingServer(); pPlayer->SetLeavingServer(true); - pPlayer->CallEvent("onPlayerBan", Arguments); + pPlayer->CallEvent(BuiltInEvents::onPlayerBan, Arguments); pPlayer->SetLeavingServer(bLeavingServer); // Check if script removed the ban @@ -11609,14 +11525,14 @@ CBan* CStaticFunctionDefinitions::AddBan(SString strIP, SString strUsername, SSt // Call the event with the responsible player as the source CLuaArguments Arguments; Arguments.PushBan(pBan); - pResponsible->CallEvent("onBan", Arguments); + pResponsible->CallEvent(BuiltInEvents::onBan, Arguments); } else { // Call the event with the root element as the source CLuaArguments Arguments; Arguments.PushBan(pBan); - m_pMapManager->GetRootElement()->CallEvent("onBan", Arguments); + m_pMapManager->GetRootElement()->CallEvent(BuiltInEvents::onBan, Arguments); } // Check if script removed the ban @@ -11684,7 +11600,7 @@ CBan* CStaticFunctionDefinitions::AddBan(SString strIP, SString strUsername, SSt // show him the 'kicked' message instead of our 'banned' message. const bool bLeavingServer = pPlayer->IsLeavingServer(); pPlayer->SetLeavingServer(true); - pPlayer->CallEvent("onPlayerBan", Arguments); + pPlayer->CallEvent(BuiltInEvents::onPlayerBan, Arguments); pPlayer->SetLeavingServer(bLeavingServer); // Check if script removed the ban @@ -11717,7 +11633,7 @@ bool CStaticFunctionDefinitions::RemoveBan(CBan* pBan, CPlayer* pResponsible) Arguments.PushBan(pBan); if (pResponsible) Arguments.PushElement(pResponsible); - m_pMapManager->GetRootElement()->CallEvent("onUnban", Arguments); + m_pMapManager->GetRootElement()->CallEvent(BuiltInEvents::onUnban, Arguments); // Check if script removed the ban if (pBan->IsBeingDeleted()) diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h index 18428ffda04..1914ef4b713 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -20,19 +20,11 @@ class CStaticFunctionDefinitions ~CStaticFunctionDefinitions(); // Event funcs - static bool AddEvent(CLuaMain* pLuaMain, const char* szName, const char* szArguments, bool bAllowRemoteTrigger); - static bool AddEventHandler(CLuaMain* pLuaMain, const char* szName, CElement* pElement, const CLuaFunctionRef& iLuaFunction, bool bPropagated, - EEventPriorityType eventPriority, float fPriorityMod); - static bool RemoveEventHandler(CLuaMain* pLuaMain, const char* szName, CElement* pElement, const CLuaFunctionRef& iLuaFunction); static bool TriggerEvent(const char* szName, CElement* pElement, const CLuaArguments& Arguments, bool& bWasCancelled); static bool TriggerClientEvent(const std::vector& sendList, const char* szName, CElement* pCallWithElement, CLuaArguments& Arguments); static bool TriggerLatentClientEvent(const std::vector& sendList, const char* szName, CElement* pCallWithElement, CLuaArguments& Arguments, int iBandwidth, CLuaMain* pLuaMain, ushort usResourceNetId); - static bool CancelEvent(bool bCancel, const char* szReason); - static const char* GetCancelReason(); - static bool WasEventCancelled(); - // Element create/destroy static CDummy* CreateElement(CResource* pResource, const char* szTypeName, const char* szID); static bool DestroyElement(CElement* pElement); diff --git a/Server/mods/deathmatch/logic/CTeamManager.cpp b/Server/mods/deathmatch/logic/CTeamManager.cpp index d72cc88372e..b118cfd69b0 100644 --- a/Server/mods/deathmatch/logic/CTeamManager.cpp +++ b/Server/mods/deathmatch/logic/CTeamManager.cpp @@ -63,11 +63,11 @@ CTeam* CTeamManager::Create(CElement* pParent, char* szName, unsigned char ucRed return pTeam; } -CTeam* CTeamManager::CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents) +CTeam* CTeamManager::CreateFromXML(CElement* pParent, CXMLNode& Node) { CTeam* const pTeam = new CTeam(this, pParent); - if (pTeam->GetID() == INVALID_ELEMENT_ID || !pTeam->LoadFromCustomData(pEvents, Node)) + if (pTeam->GetID() == INVALID_ELEMENT_ID || !pTeam->LoadFromCustomData(Node)) { delete pTeam; return nullptr; diff --git a/Server/mods/deathmatch/logic/CTeamManager.h b/Server/mods/deathmatch/logic/CTeamManager.h index e3b908eef32..49d9bed50c2 100644 --- a/Server/mods/deathmatch/logic/CTeamManager.h +++ b/Server/mods/deathmatch/logic/CTeamManager.h @@ -29,7 +29,7 @@ class CTeamManager CTeam* GetTeam(const char* szName); bool Exists(CTeam* pTeam); CTeam* Create(CElement* pParent, char* szName, unsigned char ucRed, unsigned char ucGreen, unsigned char ucBlue); - CTeam* CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents); + CTeam* CreateFromXML(CElement* pParent, CXMLNode& Node); std::list::const_iterator IterBegin() { return m_List.begin(); } std::list::const_iterator IterEnd() { return m_List.end(); } diff --git a/Server/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp b/Server/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp index 7da1c780c8c..2f1d4c2d39e 100644 --- a/Server/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp +++ b/Server/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp @@ -181,7 +181,7 @@ void CUnoccupiedVehicleSync::StartSync(CPlayer* pPlayer, CVehicle* pVehicle) // Call the onElementStartSync event CLuaArguments Arguments; Arguments.PushElement(pPlayer); // New syncer - pVehicle->CallEvent("onElementStartSync", Arguments); + pVehicle->CallEvent(BuiltInEvents::onElementStartSync, Arguments); } void CUnoccupiedVehicleSync::StopSync(CVehicle* pVehicle) @@ -196,7 +196,7 @@ void CUnoccupiedVehicleSync::StopSync(CVehicle* pVehicle) // Call the onElementStopSync event CLuaArguments Arguments; Arguments.PushElement(pSyncer); // Old syncer - pVehicle->CallEvent("onElementStopSync", Arguments); + pVehicle->CallEvent(BuiltInEvents::onElementStopSync, Arguments); } CPlayer* CUnoccupiedVehicleSync::FindPlayerCloseToVehicle(CVehicle* pVehicle, float fMaxDistance) @@ -315,7 +315,7 @@ void CUnoccupiedVehicleSync::Packet_UnoccupiedVehicleSync(CUnoccupiedVehicleSync // Call the onVehicleDamage event CLuaArguments Arguments; Arguments.PushNumber(fDeltaHealth); - pVehicle->CallEvent("onVehicleDamage", Arguments); + pVehicle->CallEvent(BuiltInEvents::onVehicleDamage, Arguments); } } pVehicle->SetHealth(vehicle.data.fHealth); @@ -346,7 +346,7 @@ void CUnoccupiedVehicleSync::Packet_UnoccupiedVehicleSync(CUnoccupiedVehicleSync // Execute the attach trailer script function CLuaArguments Arguments; Arguments.PushElement(pVehicle); - pCurrentTrailer->CallEvent("onTrailerDetach", Arguments); + pCurrentTrailer->CallEvent(BuiltInEvents::onTrailerDetach, Arguments); pVehicle->SetTowedVehicle(NULL); pCurrentTrailer->SetTowedByVehicle(NULL); @@ -363,7 +363,7 @@ void CUnoccupiedVehicleSync::Packet_UnoccupiedVehicleSync(CUnoccupiedVehicleSync // Execute the attach trailer script function CLuaArguments Arguments; Arguments.PushElement(pCurrentVehicle); - pTrailer->CallEvent("onTrailerDetach", Arguments); + pTrailer->CallEvent(BuiltInEvents::onTrailerDetach, Arguments); pCurrentVehicle->SetTowedVehicle(NULL); pTrailer->SetTowedByVehicle(NULL); @@ -379,7 +379,7 @@ void CUnoccupiedVehicleSync::Packet_UnoccupiedVehicleSync(CUnoccupiedVehicleSync // Execute the attach trailer script function CLuaArguments Arguments; Arguments.PushElement(pVehicle); - bool bContinue = pTrailer->CallEvent("onTrailerAttach", Arguments); + bool bContinue = pTrailer->CallEvent(BuiltInEvents::onTrailerAttach, Arguments); if (!bContinue) { @@ -409,7 +409,7 @@ void CUnoccupiedVehicleSync::Packet_UnoccupiedVehicleSync(CUnoccupiedVehicleSync // Execute the detach trailer script function CLuaArguments Arguments; Arguments.PushElement(pVehicle); - pCurrentTrailer->CallEvent("onTrailerDetach", Arguments); + pCurrentTrailer->CallEvent(BuiltInEvents::onTrailerDetach, Arguments); } } } diff --git a/Server/mods/deathmatch/logic/CVehicle.h b/Server/mods/deathmatch/logic/CVehicle.h index 10db842488c..aeb04cb3c18 100644 --- a/Server/mods/deathmatch/logic/CVehicle.h +++ b/Server/mods/deathmatch/logic/CVehicle.h @@ -16,7 +16,6 @@ class CVehicle; #include "CCommon.h" #include "packets/CPacket.h" #include "CElement.h" -#include "CEvents.h" #include "CVehicleUpgrades.h" #include "CHandlingEntry.h" diff --git a/Server/mods/deathmatch/logic/CVehicleManager.cpp b/Server/mods/deathmatch/logic/CVehicleManager.cpp index 9f8cfcec594..742cada42f7 100644 --- a/Server/mods/deathmatch/logic/CVehicleManager.cpp +++ b/Server/mods/deathmatch/logic/CVehicleManager.cpp @@ -388,12 +388,12 @@ CVehicle* CVehicleManager::Create(CElement* pParent, unsigned short usModel, uns return pVehicle; } -CVehicle* CVehicleManager::CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents) +CVehicle* CVehicleManager::CreateFromXML(CElement* pParent, CXMLNode& Node) { RandomizeRandomSeed(); CVehicle* pVehicle = new CVehicle(this, pParent, 400, 254, 254); - if (pVehicle->GetID() == INVALID_ELEMENT_ID || !pVehicle->LoadFromCustomData(pEvents, Node)) + if (pVehicle->GetID() == INVALID_ELEMENT_ID || !pVehicle->LoadFromCustomData(Node)) { delete pVehicle; return nullptr; diff --git a/Server/mods/deathmatch/logic/CVehicleManager.h b/Server/mods/deathmatch/logic/CVehicleManager.h index 45830ee89f6..345722e6e67 100644 --- a/Server/mods/deathmatch/logic/CVehicleManager.h +++ b/Server/mods/deathmatch/logic/CVehicleManager.h @@ -31,7 +31,7 @@ class CVehicleManager ~CVehicleManager(); CVehicle* Create(CElement* pParent, unsigned short usModel, unsigned char ucVariant, unsigned char ucVariant2); - CVehicle* CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents); + CVehicle* CreateFromXML(CElement* pParent, CXMLNode& Node); void DeleteAll(); bool Exists(CVehicle* pVehicle); diff --git a/Server/mods/deathmatch/logic/CWaterManager.cpp b/Server/mods/deathmatch/logic/CWaterManager.cpp index 77025ccdd5f..13bf6849b0b 100644 --- a/Server/mods/deathmatch/logic/CWaterManager.cpp +++ b/Server/mods/deathmatch/logic/CWaterManager.cpp @@ -39,11 +39,11 @@ CWater* CWaterManager::Create(CWater::EWaterType waterType, CElement* pParent, b return pWater; } -CWater* CWaterManager::CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents) +CWater* CWaterManager::CreateFromXML(CElement* pParent, CXMLNode& Node) { CWater* const pWater = new CWater(this, pParent); - if (pWater->GetID() == INVALID_ELEMENT_ID || !pWater->LoadFromCustomData(pEvents, Node)) + if (pWater->GetID() == INVALID_ELEMENT_ID || !pWater->LoadFromCustomData(Node)) { delete pWater; return nullptr; diff --git a/Server/mods/deathmatch/logic/CWaterManager.h b/Server/mods/deathmatch/logic/CWaterManager.h index b05a3cfe5c0..2ac4f8a3a9a 100644 --- a/Server/mods/deathmatch/logic/CWaterManager.h +++ b/Server/mods/deathmatch/logic/CWaterManager.h @@ -22,7 +22,7 @@ class CWaterManager ~CWaterManager(); CWater* Create(CWater::EWaterType waterType, CElement* pParent, bool bShallow = false); - CWater* CreateFromXML(CElement* pParent, CXMLNode& Node, CEvents* pEvents); + CWater* CreateFromXML(CElement* pParent, CXMLNode& Node); void DeleteAll(); unsigned int Count() { return static_cast(m_List.size()); }; diff --git a/Server/mods/deathmatch/logic/lua/CLuaFunctionDefs.Event.cpp b/Server/mods/deathmatch/logic/lua/CLuaFunctionDefs.Event.cpp index fcec28e953e..69cb334ab78 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaFunctionDefs.Event.cpp +++ b/Server/mods/deathmatch/logic/lua/CLuaFunctionDefs.Event.cpp @@ -10,139 +10,41 @@ *****************************************************************************/ #include "StdInc.h" +#include +#include + #define MIN_SERVER_REQ_TRIGGERCLIENTEVENT_SENDLIST "1.3.0-9.04570" -int CLuaFunctionDefs::AddEvent(lua_State* luaVM) +const Event* ResolveEvent(const std::string& name) { - // bool addEvent ( string eventName [, bool allowRemoteTrigger = false ] ) - SString strName; - bool bAllowRemoteTrigger; - - CScriptArgReader argStream(luaVM); - argStream.ReadString(strName); - argStream.ReadBool(bAllowRemoteTrigger, false); - - if (!argStream.HasErrors()) - { - // Grab our virtual machine - CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); - if (pLuaMain) - { - // Do it - if (CStaticFunctionDefinitions::AddEvent(pLuaMain, strName, "", bAllowRemoteTrigger)) - { - lua_pushboolean(luaVM, true); - return 1; - } - } - } - else - m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); - - lua_pushboolean(luaVM, false); - return 1; + if (const Event* event = Event::Get(name)) + return event; + throw std::invalid_argument("Event doesn't exist"); } -int CLuaFunctionDefs::AddEventHandler(lua_State* luaVM) +bool CLuaFunctionDefs::RemoveEventHandler(lua_State* L, std::string eventName, CElement* attachedTo, CLuaFunctionRef handlerfn) { - // bool addEventHandler ( string eventName, element attachedTo, function handlerFunction [, bool getPropagated = true, string priority = "normal" ] ) - SString strName; - CElement* pElement; - CLuaFunctionRef iLuaFunction; - bool bPropagated; - SString strPriority; - - CScriptArgReader argStream(luaVM); - argStream.ReadString(strName); - argStream.ReadUserData(pElement); - argStream.ReadFunction(iLuaFunction); - argStream.ReadBool(bPropagated, true); - argStream.ReadString(strPriority, "normal"); - argStream.ReadFunctionComplete(); - - // Check if strPriority has a number as well. e.g. name+1 or name-1.32 - float fPriorityMod = 0; - EEventPriorityType eventPriority; - { - size_t iPos = strPriority.find_first_of("-+"); - if (iPos != SString::npos) - { - fPriorityMod = static_cast(atof(strPriority.SubStr(iPos))); - strPriority = strPriority.Left(iPos); - } - - if (!StringToEnum(strPriority, eventPriority)) - argStream.SetTypeError(GetEnumTypeName(eventPriority), 5); // priority is argument #5 - } - - if (!argStream.HasErrors()) - { - // Grab our virtual machine - CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); - if (pLuaMain) - { - CResourceFile* file = pLuaMain->GetResourceFile(); - if (file && file->GetType() == CResourceFile::RESOURCE_FILE_TYPE_HTML) - { - argStream.SetCustomError("You cannot have event handlers in HTML scripts"); - } - else - { - // check if the handle is in use - if (pElement->GetEventManager()->HandleExists(pLuaMain, strName, iLuaFunction)) - { - argStream.SetCustomError(SString("'%s' with this function is already handled", *strName)); - } - else - { - // Do it - if (CStaticFunctionDefinitions::AddEventHandler(pLuaMain, strName, pElement, iLuaFunction, bPropagated, eventPriority, fPriorityMod)) - { - lua_pushboolean(luaVM, true); - return 1; - } - } - } - } - } - if (argStream.HasErrors()) - m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); - - lua_pushboolean(luaVM, false); - return 1; + return attachedTo->GetEventHandlerCallDispatcher().Remove(*ResolveEvent(eventName), m_pLuaManager->GetVirtualMachine(L), handlerfn); } -int CLuaFunctionDefs::RemoveEventHandler(lua_State* luaVM) +bool CLuaFunctionDefs::AddEventHandler(lua_State* L, std::string eventName, CElement* attachedTo, + CLuaFunctionRef handlerfn, std::optional propagated, std::optional priorityToParse) { - // bool removeEventHandler ( string eventName, element attachedTo, function functionVar ) - SString strName; - CElement* pElement; - CLuaFunctionRef iLuaFunction; + EventHandler::Priority priority{ priorityToParse.value_or("") }; // Might throw invalid_argument - CScriptArgReader argStream(luaVM); - argStream.ReadString(strName); - argStream.ReadUserData(pElement); - argStream.ReadFunction(iLuaFunction); - argStream.ReadFunctionComplete(); + const Event* event = ResolveEvent(eventName); + std::cout << "Add event " << eventName << "[Priority: " << priority.ToString() << "]\n"; // TODO Remove - if (!argStream.HasErrors()) - { - // Grab our virtual machine - CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); - if (pLuaMain) - { - if (CStaticFunctionDefinitions::RemoveEventHandler(pLuaMain, strName, pElement, iLuaFunction)) - { - lua_pushboolean(luaVM, true); - return 1; - } - } - } - else - m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + return attachedTo->GetEventHandlerCallDispatcher().Add(*event, + { priority, m_pLuaManager->GetVirtualMachine(L), handlerfn, propagated.value_or(true) } + ); +} - lua_pushboolean(luaVM, false); - return 1; +bool CLuaFunctionDefs::AddEvent(lua_State* L, std::string name, std::optional allowRemoteTrigger) +{ + if (name.empty()) + return false; // Invalid name (maybe throw here?) + return CustomEvent::Add(name, m_pLuaManager->GetVirtualMachine(L), allowRemoteTrigger.value_or(false)); } int CLuaFunctionDefs::GetEventHandlers(lua_State* luaVM) @@ -157,16 +59,17 @@ int CLuaFunctionDefs::GetEventHandlers(lua_State* luaVM) if (!argStream.HasErrors()) { - // Grab our virtual machine - CLuaMain* pLuaMain = m_pLuaManager->GetVirtualMachine(luaVM); - if (pLuaMain) + if (CLuaMain* lmain = m_pLuaManager->GetVirtualMachine(luaVM)) { - // Create a new table - lua_newtable(luaVM); - - pElement->GetEventManager()->GetHandles(pLuaMain, (const char*)strName, luaVM); - - return 1; + if (auto* event = Event::Get(strName)) + { + if (auto* handlers = pElement->GetEventHandlerCallDispatcher().GetHandlers(*event)) + { + lua_newtable(luaVM); + handlers->PushToLua(lmain, luaVM); + return 1; + } + } } } else @@ -191,11 +94,9 @@ int CLuaFunctionDefs::TriggerEvent(lua_State* luaVM) if (!argStream.HasErrors()) { - // Trigger it - bool bWasCancelled; - if (CStaticFunctionDefinitions::TriggerEvent(strName, pElement, Arguments, bWasCancelled)) + if (auto* event = Event::Get(strName)) { - lua_pushboolean(luaVM, !bWasCancelled); + lua_pushboolean(luaVM, !pElement->CallEvent(*event, Arguments)); return 1; } } @@ -477,44 +378,18 @@ int CLuaFunctionDefs::RemoveDebugHook(lua_State* luaVM) return 1; } -int CLuaFunctionDefs::CancelEvent(lua_State* luaVM) +bool CLuaFunctionDefs::CancelEvent(std::optional cancel, std::optional reason) { - // bool cancelEvent ( [ bool cancel = true, string reason = "" ] ) - bool bCancel; - SString strReason; - - CScriptArgReader argStream(luaVM); - argStream.ReadBool(bCancel, true); - argStream.ReadString(strReason, ""); - - if (!argStream.HasErrors()) - { - CStaticFunctionDefinitions::CancelEvent(bCancel, strReason); - - lua_pushboolean(luaVM, true); - return 1; - } - else - m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); - - lua_pushboolean(luaVM, false); - return 1; + s_EventDispatcher.CancelEvent(cancel.value_or(true), std::string{ reason.value_or("") }); + return true; } -int CLuaFunctionDefs::GetCancelReason(lua_State* luaVM) +const std::string& CLuaFunctionDefs::GetCancelReason() { - const char* szReason = CStaticFunctionDefinitions::GetCancelReason(); - if (szReason) - { - lua_pushstring(luaVM, szReason); - return 1; - } - lua_pushboolean(luaVM, false); - return 1; + return s_EventDispatcher.GetCancelReason(); } -int CLuaFunctionDefs::WasEventCancelled(lua_State* luaVM) +bool CLuaFunctionDefs::WasEventCancelled() { - lua_pushboolean(luaVM, CStaticFunctionDefinitions::WasEventCancelled()); - return 1; + return s_EventDispatcher.WasEventCancelled(); } diff --git a/Server/mods/deathmatch/logic/lua/CLuaFunctionDefs.h b/Server/mods/deathmatch/logic/lua/CLuaFunctionDefs.h index 120d712be03..aca8d4d369e 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaFunctionDefs.h +++ b/Server/mods/deathmatch/logic/lua/CLuaFunctionDefs.h @@ -23,6 +23,9 @@ class CAccessControlListManager; #include "LuaCommon.h" #include "CLuaMain.h" #include "CLuaTimerManager.h" +#include +#include +#include #define LUA_ERROR() lua_pushboolean ( luaVM, false ); return 0; #define LUA_DECLARE(x) static int x ( lua_State * luaVM ); @@ -36,15 +39,16 @@ class CLuaFunctionDefs static void Initialize(class CLuaManager* pLuaManager, class CGame* pClientGame); // Event functions - LUA_DECLARE(AddEvent); - LUA_DECLARE(AddEventHandler); - LUA_DECLARE(RemoveEventHandler); + static bool RemoveEventHandler(lua_State* L, std::string eventName, CElement* attachedTo, CLuaFunctionRef handlerfn); + static bool AddEventHandler(lua_State* L, std::string eventName, CElement* attachedTo, + CLuaFunctionRef handlerfn, std::optional propagated, std::optional priorityToParse); + static bool AddEvent(lua_State* L, std::string name, std::optional allowRemoteTrigger); + static bool CancelEvent(std::optional cancel, std::optional reason); + static const std::string& GetCancelReason(); + static bool WasEventCancelled(); LUA_DECLARE(GetEventHandlers); LUA_DECLARE(TriggerEvent); LUA_DECLARE(TriggerClientEvent); - LUA_DECLARE(CancelEvent); - LUA_DECLARE(GetCancelReason); - LUA_DECLARE(WasEventCancelled); LUA_DECLARE(TriggerLatentClientEvent); LUA_DECLARE(GetLatentEventHandles); LUA_DECLARE(GetLatentEventStatus); diff --git a/Server/mods/deathmatch/logic/lua/CLuaMain.cpp b/Server/mods/deathmatch/logic/lua/CLuaMain.cpp index fa83d6b46d8..bd02722a009 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaMain.cpp +++ b/Server/mods/deathmatch/logic/lua/CLuaMain.cpp @@ -26,6 +26,7 @@ extern CNetServer* g_pRealNetServer; #include "luascripts/coroutine_debug.lua.h" #include "luascripts/exports.lua.h" #include "luascripts/inspect.lua.h" +#include "luascripts/DispatchEvent.lua.h" CLuaMain::CLuaMain(CLuaManager* pLuaManager, CObjectManager* pObjectManager, CPlayerManager* pPlayerManager, CVehicleManager* pVehicleManager, CBlipManager* pBlipManager, CRadarAreaManager* pRadarAreaManager, CMapManager* pMapManager, CResource* pResourceOwner, bool bEnableOOP) @@ -212,6 +213,19 @@ void CLuaMain::InitVM() LoadScript(EmbeddedLuaCode::exports); LoadScript(EmbeddedLuaCode::coroutine_debug); LoadScript(EmbeddedLuaCode::inspect); + { + LoadScript(EmbeddedLuaCode::DispatchEvent); + + lua_getglobal(m_luaVM, "DispatchEvent"); + //const auto ptr = lua_topointer(m_luaVM, -1); + //const int ref = lua_ref(m_luaVM, true); // it pops the value + //m_fnDispatchEvent = { m_luaVM, ref, ptr }; + m_fnrefDispatchEvent = lua_ref(m_luaVM, true); + dassert(m_fnrefDispatchEvent != LUA_REFNIL); + + lua_pushnil(m_luaVM); + lua_setglobal(m_luaVM, "DispatchEvent"); // nil function out, so it doesn't conflit with people's code + } } // Special function(s) that are only visible to HTMLD scripts diff --git a/Server/mods/deathmatch/logic/lua/CLuaMain.h b/Server/mods/deathmatch/logic/lua/CLuaMain.h index d8b4dcc3d72..954dc243916 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaMain.h +++ b/Server/mods/deathmatch/logic/lua/CLuaMain.h @@ -109,6 +109,7 @@ class CLuaMain //: public CClient static int LuaLoadBuffer(lua_State* L, const char* buff, size_t sz, const char* name); static int OnUndump(const char* p, size_t n); + int GetDispatchEventFnRef() const { return m_fnrefDispatchEvent; } private: void InitSecurity(); void InitClasses(lua_State* luaVM); @@ -150,6 +151,9 @@ class CLuaMain //: public CClient uint m_uiOpenXMLFileCountWarnThresh; static SString ms_strExpectedUndumpHash; + // Ref to special event handler function from internal script in InitVM() + // Code: "luascripts/DispatchEvent.lua.h" + int m_fnrefDispatchEvent; public: CFastHashMap m_CallbackTable; std::map m_FunctionTagMap; diff --git a/Server/mods/deathmatch/logic/lua/CLuaManager.cpp b/Server/mods/deathmatch/logic/lua/CLuaManager.cpp index b5b660ee2c4..cbb5fda491b 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaManager.cpp +++ b/Server/mods/deathmatch/logic/lua/CLuaManager.cpp @@ -11,11 +11,13 @@ #include "StdInc.h" #include "../luadefs/CLuaGenericDefs.h" +#include +#include extern CGame* g_pGame; CLuaManager::CLuaManager(CObjectManager* pObjectManager, CPlayerManager* pPlayerManager, CVehicleManager* pVehicleManager, CBlipManager* pBlipManager, - CRadarAreaManager* pRadarAreaManager, CRegisteredCommands* pRegisteredCommands, CMapManager* pMapManager, CEvents* pEvents) + CRadarAreaManager* pRadarAreaManager, CRegisteredCommands* pRegisteredCommands, CMapManager* pMapManager) { m_pObjectManager = pObjectManager; m_pPlayerManager = pPlayerManager; @@ -24,7 +26,6 @@ CLuaManager::CLuaManager(CObjectManager* pObjectManager, CPlayerManager* pPlayer m_pRadarAreaManager = pRadarAreaManager; m_pRegisteredCommands = pRegisteredCommands; m_pMapManager = pMapManager; - m_pEvents = pEvents; // Create our lua dynamic module manager m_pLuaModuleManager = new CLuaModuleManager(this); @@ -75,7 +76,7 @@ bool CLuaManager::RemoveVirtualMachine(CLuaMain* pLuaMain) if (pLuaMain) { // Remove all events registered by it and all commands added - m_pEvents->RemoveAllEvents(pLuaMain); + s_CustomEvents.RemoveAllOf(pLuaMain); m_pRegisteredCommands->CleanUpForVM(pLuaMain); // Delete it unless it is already @@ -157,15 +158,16 @@ CResource* CLuaManager::GetVirtualMachineResource(lua_State* luaVM) void CLuaManager::LoadCFunctions() { constexpr static const std::pair functions[]{ - {"addEvent", CLuaFunctionDefs::AddEvent}, - {"addEventHandler", CLuaFunctionDefs::AddEventHandler}, - {"removeEventHandler", CLuaFunctionDefs::RemoveEventHandler}, + {"addEvent", CLuaDefs::ArgumentParserWarn}, + {"addEventHandler", CLuaDefs::ArgumentParserWarn}, + {"removeEventHandler", CLuaDefs::ArgumentParserWarn}, + {"cancelEvent", CLuaDefs::ArgumentParserWarn}, + {"wasEventCancelled", CLuaDefs::ArgumentParserWarn}, + {"getCancelReason", CLuaDefs::ArgumentParserWarn}, + {"getEventHandlers", CLuaFunctionDefs::GetEventHandlers}, {"triggerEvent", CLuaFunctionDefs::TriggerEvent}, {"triggerClientEvent", CLuaFunctionDefs::TriggerClientEvent}, - {"cancelEvent", CLuaFunctionDefs::CancelEvent}, - {"wasEventCancelled", CLuaFunctionDefs::WasEventCancelled}, - {"getCancelReason", CLuaFunctionDefs::GetCancelReason}, {"triggerLatentClientEvent", CLuaFunctionDefs::TriggerLatentClientEvent}, {"getLatentEventHandles", CLuaFunctionDefs::GetLatentEventHandles}, {"getLatentEventStatus", CLuaFunctionDefs::GetLatentEventStatus}, diff --git a/Server/mods/deathmatch/logic/lua/CLuaManager.h b/Server/mods/deathmatch/logic/lua/CLuaManager.h index fd1dcdc6c5b..be56154fbbd 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaManager.h +++ b/Server/mods/deathmatch/logic/lua/CLuaManager.h @@ -15,13 +15,11 @@ class CLuaManager; #pragma once #include -#include "../CEvents.h" #include "CLuaMain.h" #include "CLuaCFunctions.h" // Predeclarations class CBlipManager; -class CEvents; class CMapManager; class CObjectManager; class CPlayerManager; @@ -33,7 +31,7 @@ class CLuaManager { public: CLuaManager(CObjectManager* pObjectManager, CPlayerManager* pPlayerManager, CVehicleManager* pVehicleManager, CBlipManager* pBlipManager, - CRadarAreaManager* pRadarAreaManager, CRegisteredCommands* pRegisteredCommands, CMapManager* pMapManager, CEvents* pEvents); + CRadarAreaManager* pRadarAreaManager, CRegisteredCommands* pRegisteredCommands, CMapManager* pMapManager); ~CLuaManager(); CLuaMain* CreateVirtualMachine(CResource* pResourceOwner, bool bEnableOOP); @@ -60,7 +58,6 @@ class CLuaManager class CRegisteredCommands* m_pRegisteredCommands; CVehicleManager* m_pVehicleManager; CMapManager* m_pMapManager; - CEvents* m_pEvents; CLuaModuleManager* m_pLuaModuleManager; CFastHashMap m_VirtualMachineMap; diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaDefs.h index bce533c5dde..e8f8a656d74 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaDefs.h @@ -86,7 +86,7 @@ class CLuaDefs static CAccessControlListManager* m_pACLManager; static CMainConfig* m_pMainConfig; -protected: +public: // Old style: Only warn on failure. This should // not be used for new functions. ReturnOnError // must be a value to use as result on invalid argument diff --git a/Server/mods/deathmatch/logic/packets/CLuaEventPacket.h b/Server/mods/deathmatch/logic/packets/CLuaEventPacket.h index 9b78214c827..5cceb3f38c3 100644 --- a/Server/mods/deathmatch/logic/packets/CLuaEventPacket.h +++ b/Server/mods/deathmatch/logic/packets/CLuaEventPacket.h @@ -26,9 +26,9 @@ class CLuaEventPacket final : public CPacket bool Read(NetBitStreamInterface& BitStream); bool Write(NetBitStreamInterface& BitStream) const; - const char* GetName() { return m_strName; } - ElementID GetElementID() { return m_ElementID; } - CLuaArguments* GetArguments() { return m_pArguments; } + const std::string& GetName() { return m_strName; } + ElementID GetElementID() { return m_ElementID; } + CLuaArguments* GetArguments() { return m_pArguments; } private: SString m_strName; diff --git a/Server/mods/deathmatch/logic/packets/CPlayerPuresyncPacket.cpp b/Server/mods/deathmatch/logic/packets/CPlayerPuresyncPacket.cpp index 04f0912d661..ff865b13432 100644 --- a/Server/mods/deathmatch/logic/packets/CPlayerPuresyncPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CPlayerPuresyncPacket.cpp @@ -77,7 +77,7 @@ bool CPlayerPuresyncPacket::Read(NetBitStreamInterface& BitStream) else Arguments.PushNil(); - pSourcePlayer->CallEvent("onPlayerContact", Arguments); + pSourcePlayer->CallEvent(BuiltInEvents::onPlayerContact, Arguments); } // Player position @@ -260,7 +260,7 @@ bool CPlayerPuresyncPacket::Read(NetBitStreamInterface& BitStream) Arguments.PushNumber(pSourcePlayer->GetAttackBodyPart()); Arguments.PushNumber(fDamage); - pSourcePlayer->CallEvent("onPlayerDamage", Arguments); + pSourcePlayer->CallEvent(BuiltInEvents::onPlayerDamage, Arguments); } // Success diff --git a/Server/mods/deathmatch/logic/packets/CVehiclePuresyncPacket.cpp b/Server/mods/deathmatch/logic/packets/CVehiclePuresyncPacket.cpp index 9aa6aa76a49..3360f44a734 100644 --- a/Server/mods/deathmatch/logic/packets/CVehiclePuresyncPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CVehiclePuresyncPacket.cpp @@ -154,7 +154,7 @@ bool CVehiclePuresyncPacket::Read(NetBitStreamInterface& BitStream) // Call the onVehicleDamage event CLuaArguments Arguments; Arguments.PushNumber(fDeltaHealth); - pVehicle->CallEvent("onVehicleDamage", Arguments); + pVehicle->CallEvent(BuiltInEvents::onVehicleDamage, Arguments); } } pVehicle->SetHealth(fHealth); @@ -208,7 +208,7 @@ bool CVehiclePuresyncPacket::Read(NetBitStreamInterface& BitStream) // Execute the attach trailer script function CLuaArguments Arguments; Arguments.PushElement(pTowedByVehicle); - pCurrentTrailer->CallEvent("onTrailerDetach", Arguments); + pCurrentTrailer->CallEvent(BuiltInEvents::onTrailerDetach, Arguments); } // If something else is towing this trailer @@ -225,7 +225,7 @@ bool CVehiclePuresyncPacket::Read(NetBitStreamInterface& BitStream) // Execute the attach trailer script function CLuaArguments Arguments; Arguments.PushElement(pCurrentVehicle); - pTrailer->CallEvent("onTrailerDetach", Arguments); + pTrailer->CallEvent(BuiltInEvents::onTrailerDetach, Arguments); } pTowedByVehicle->SetTowedVehicle(pTrailer); @@ -234,7 +234,7 @@ bool CVehiclePuresyncPacket::Read(NetBitStreamInterface& BitStream) // Execute the attach trailer script function CLuaArguments Arguments; Arguments.PushElement(pTowedByVehicle); - bool bContinue = pTrailer->CallEvent("onTrailerAttach", Arguments); + bool bContinue = pTrailer->CallEvent(BuiltInEvents::onTrailerAttach, Arguments); // Attach or detach trailers depending on the event outcome CVehicleTrailerPacket TrailerPacket(pTowedByVehicle, pTrailer, bContinue); @@ -264,7 +264,7 @@ bool CVehiclePuresyncPacket::Read(NetBitStreamInterface& BitStream) // Execute the detach trailer script function CLuaArguments Arguments; Arguments.PushElement(pTowedByVehicle); - pCurrentTrailer->CallEvent("onTrailerDetach", Arguments); + pCurrentTrailer->CallEvent(BuiltInEvents::onTrailerDetach, Arguments); } } @@ -309,7 +309,7 @@ bool CVehiclePuresyncPacket::Read(NetBitStreamInterface& BitStream) Arguments.PushNumber(false); Arguments.PushNumber(false); Arguments.PushNumber(fHealthLoss); - pSourcePlayer->CallEvent("onPlayerDamage", Arguments); + pSourcePlayer->CallEvent(BuiltInEvents::onPlayerDamage, Arguments); } else { @@ -324,7 +324,7 @@ bool CVehiclePuresyncPacket::Read(NetBitStreamInterface& BitStream) Arguments.PushNumber(pSourcePlayer->GetAttackWeapon()); Arguments.PushNumber(pSourcePlayer->GetAttackBodyPart()); Arguments.PushNumber(fHealthLoss); - pSourcePlayer->CallEvent("onPlayerDamage", Arguments); + pSourcePlayer->CallEvent(BuiltInEvents::onPlayerDamage, Arguments); } } pSourcePlayer->SetHealth(fHealth); @@ -349,7 +349,7 @@ bool CVehiclePuresyncPacket::Read(NetBitStreamInterface& BitStream) Arguments.PushNumber(false); Arguments.PushNumber(false); Arguments.PushNumber(fArmorLoss); - pSourcePlayer->CallEvent("onPlayerDamage", Arguments); + pSourcePlayer->CallEvent(BuiltInEvents::onPlayerDamage, Arguments); } else { @@ -364,7 +364,7 @@ bool CVehiclePuresyncPacket::Read(NetBitStreamInterface& BitStream) Arguments.PushNumber(pSourcePlayer->GetAttackWeapon()); Arguments.PushNumber(pSourcePlayer->GetAttackBodyPart()); Arguments.PushNumber(fArmorLoss); - pSourcePlayer->CallEvent("onPlayerDamage", Arguments); + pSourcePlayer->CallEvent(BuiltInEvents::onPlayerDamage, Arguments); } } pSourcePlayer->SetArmor(fArmor); diff --git a/Shared/mods/deathmatch/logic/CDebugHookManager.cpp b/Shared/mods/deathmatch/logic/CDebugHookManager.cpp index fd2f0c10ca3..742f12e73d7 100644 --- a/Shared/mods/deathmatch/logic/CDebugHookManager.cpp +++ b/Shared/mods/deathmatch/logic/CDebugHookManager.cpp @@ -206,9 +206,9 @@ void GetDebugInfo(lua_State* luaVM, lua_Debug& debugInfo, const char*& szFilenam // Get current Lua source file and line number // /////////////////////////////////////////////////////////////// -void GetMapEventDebugInfo(CMapEvent* pMapEvent, const char*& szFilename, int& iLineNumber) +void GetMapEventDebugInfo(const EventHandler& handler, const char*& szFilename, int& iLineNumber) { - CLuaMain* pLuaMain = pMapEvent->GetVM(); + CLuaMain* pLuaMain = handler.GetLuaMain(); if (!pLuaMain) return; @@ -218,7 +218,7 @@ void GetMapEventDebugInfo(CMapEvent* pMapEvent, const char*& szFilename, int& iL if (!luaVM) return; - const CLuaFunctionRef& iLuaFunction = pMapEvent->GetLuaFunction(); + const CLuaFunctionRef& iLuaFunction = handler.GetCallback(); lua_Debug debugInfo; lua_getref(luaVM, iLuaFunction.ToInt()); @@ -348,19 +348,19 @@ void CDebugHookManager::GetFunctionCallHookArguments(CLuaArguments& NewArguments // Returns false if event should be skipped // /////////////////////////////////////////////////////////////// -bool CDebugHookManager::OnPreEvent(const char* szName, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller) +bool CDebugHookManager::OnPreEvent(const std::string& name, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller) { if (m_PreEventHookList.empty()) return true; // Check if named event is pre hooked - if (!IsNameAllowed(szName, m_PreEventHookList)) + if (!IsNameAllowed(name, m_PreEventHookList)) return true; CLuaArguments NewArguments; - GetEventCallHookArguments(NewArguments, szName, Arguments, pSource, pCaller); + GetEventCallHookArguments(NewArguments, name, Arguments, pSource, pCaller); - return CallHook(szName, m_PreEventHookList, NewArguments); + return CallHook(name, m_PreEventHookList, NewArguments); } /////////////////////////////////////////////////////////////// @@ -370,19 +370,19 @@ bool CDebugHookManager::OnPreEvent(const char* szName, const CLuaArguments& Argu // Called after a Lua event is triggered // /////////////////////////////////////////////////////////////// -void CDebugHookManager::OnPostEvent(const char* szName, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller) +void CDebugHookManager::OnPostEvent(const std::string& name, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller) { if (m_PostEventHookList.empty()) return; // Check if named event is post hooked - if (!IsNameAllowed(szName, m_PostEventHookList)) + if (!IsNameAllowed(name, m_PostEventHookList)) return; CLuaArguments NewArguments; - GetEventCallHookArguments(NewArguments, szName, Arguments, pSource, pCaller); + GetEventCallHookArguments(NewArguments, name, Arguments, pSource, pCaller); - CallHook(szName, m_PostEventHookList, NewArguments); + CallHook(name, m_PostEventHookList, NewArguments); } /////////////////////////////////////////////////////////////// @@ -425,19 +425,19 @@ void CDebugHookManager::GetEventCallHookArguments(CLuaArguments& NewArguments, c // Returns false if function call should be skipped // /////////////////////////////////////////////////////////////// -bool CDebugHookManager::OnPreEventFunction(const char* szName, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller, CMapEvent* pMapEvent) +bool CDebugHookManager::OnPreEventFunction(const std::string& name, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller, const EventHandler& handler) { if (m_PreEventFunctionHookList.empty()) return true; // Check if named event function is pre hooked - if (!IsNameAllowed(szName, m_PreEventFunctionHookList)) + if (!IsNameAllowed(name, m_PreEventFunctionHookList)) return true; CLuaArguments NewArguments; - GetEventFunctionCallHookArguments(NewArguments, szName, Arguments, pSource, pCaller, pMapEvent); + GetEventFunctionCallHookArguments(NewArguments, name, Arguments, pSource, pCaller, handler); - return CallHook(szName, m_PreEventFunctionHookList, NewArguments); + return CallHook(name, m_PreEventFunctionHookList, NewArguments); } /////////////////////////////////////////////////////////////// @@ -447,19 +447,19 @@ bool CDebugHookManager::OnPreEventFunction(const char* szName, const CLuaArgumen // Called after a Lua event function is called // /////////////////////////////////////////////////////////////// -void CDebugHookManager::OnPostEventFunction(const char* szName, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller, CMapEvent* pMapEvent) +void CDebugHookManager::OnPostEventFunction(const std::string& name, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller, const EventHandler& handler) { if (m_PostEventFunctionHookList.empty()) return; // Check if named event function is post hooked - if (!IsNameAllowed(szName, m_PostEventFunctionHookList)) + if (!IsNameAllowed(name, m_PostEventFunctionHookList)) return; CLuaArguments NewArguments; - GetEventFunctionCallHookArguments(NewArguments, szName, Arguments, pSource, pCaller, pMapEvent); + GetEventFunctionCallHookArguments(NewArguments, name, Arguments, pSource, pCaller, handler); - CallHook(szName, m_PostEventFunctionHookList, NewArguments); + CallHook(name, m_PostEventFunctionHookList, NewArguments); } /////////////////////////////////////////////////////////////// @@ -469,7 +469,7 @@ void CDebugHookManager::OnPostEventFunction(const char* szName, const CLuaArgume // Get call hook arguments for OnPre/PostEventFunction // /////////////////////////////////////////////////////////////// -void CDebugHookManager::GetEventFunctionCallHookArguments(CLuaArguments& NewArguments, const SString& strName, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller, CMapEvent* pMapEvent) +void CDebugHookManager::GetEventFunctionCallHookArguments(CLuaArguments& NewArguments, const SString& strName, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller, const EventHandler& handler) { CLuaMain* pEventLuaMain = g_pGame->GetScriptDebugging()->GetTopLuaMain(); CResource* pEventResource = pEventLuaMain ? pEventLuaMain->GetResource() : NULL; @@ -485,9 +485,9 @@ void CDebugHookManager::GetEventFunctionCallHookArguments(CLuaArguments& NewArgu // Get file/line number for function const char* szFunctionFilename = ""; int iFunctionLineNumber = 0; - GetMapEventDebugInfo(pMapEvent, szFunctionFilename, iFunctionLineNumber); + GetMapEventDebugInfo(handler, szFunctionFilename, iFunctionLineNumber); - CLuaMain* pFunctionLuaMain = pMapEvent->GetVM(); + CLuaMain* pFunctionLuaMain = handler.GetLuaMain(); CResource* pFunctionResource = pFunctionLuaMain ? pFunctionLuaMain->GetResource() : NULL; // resource eventResource, string eventName, element eventSource, element eventClient, string eventFilename, int eventLineNumber, @@ -520,7 +520,7 @@ void CDebugHookManager::GetEventFunctionCallHookArguments(CLuaArguments& NewArgu // Returns true if there is a debughook which handles the name // /////////////////////////////////////////////////////////////// -bool CDebugHookManager::IsNameAllowed(const char* szName, const std::vector& eventHookList, bool bNameMustBeExplicitlyAllowed) +bool CDebugHookManager::IsNameAllowed(const std::string& name, const std::vector& eventHookList, bool bNameMustBeExplicitlyAllowed) { for (uint i = 0; i < eventHookList.size(); i++) { @@ -529,7 +529,7 @@ bool CDebugHookManager::IsNameAllowed(const char* szName, const std::vector& eventHookList, const CLuaArguments& Arguments, +bool CDebugHookManager::CallHook(const std::string& name, const std::vector& eventHookList, const CLuaArguments& Arguments, bool bNameMustBeExplicitlyAllowed) { static bool bRecurse = false; @@ -608,7 +608,7 @@ bool CDebugHookManager::CallHook(const char* szName, const std::vector + #ifdef MTA_CLIENT #define CElement CClientEntity #define CPlayer CClientPlayer @@ -53,21 +55,21 @@ class CDebugHookManager bool OnPreFunction(lua_CFunction f, lua_State* luaVM, bool bAllowed); void OnPostFunction(lua_CFunction f, lua_State* luaVM); - bool OnPreEvent(const char* szName, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller); - void OnPostEvent(const char* szName, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller); - bool OnPreEventFunction(const char* szName, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller, CMapEvent* pMapEvent); - void OnPostEventFunction(const char* szName, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller, CMapEvent* pMapEvent); + bool OnPreEvent(const std::string& name, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller); + void OnPostEvent(const std::string& name, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller); + bool OnPreEventFunction(const std::string& name, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller, const EventHandler& handler); + void OnPostEventFunction(const std::string& name, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller, const EventHandler& handler); bool HasPostFunctionHooks() const { return !m_PostFunctionHookList.empty() || m_uiPostFunctionOverride; } protected: void GetFunctionCallHookArguments(CLuaArguments& NewArguments, const SString& strName, lua_State* luaVM, bool bAllowed); - void GetEventFunctionCallHookArguments(CLuaArguments& NewArguments, const SString& strName, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller, CMapEvent* pMapEvent); + void GetEventFunctionCallHookArguments(CLuaArguments& NewArguments, const SString& strName, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller, const EventHandler& handler); void GetEventCallHookArguments(CLuaArguments& NewArguments, const SString& strName, const CLuaArguments& Arguments, CElement* pSource, CPlayer* pCaller); std::vector& GetHookInfoListForType(EDebugHookType hookType); - bool CallHook(const char* szName, const std::vector& eventHookList, const CLuaArguments& Arguments, + bool CallHook(const std::string& name, const std::vector& eventHookList, const CLuaArguments& Arguments, bool bNameMustBeExplicitlyAllowed = false); - bool IsNameAllowed(const char* szName, const std::vector& eventHookList, bool bNameMustBeExplicitlyAllowed = false); + bool IsNameAllowed(const std::string& name, const std::vector& eventHookList, bool bNameMustBeExplicitlyAllowed = false); bool MustNameBeExplicitlyAllowed(const SString& strName); void MaybeMaskArgumentValues(const SString& strFunctionName, CLuaArguments& FunctionArguments); diff --git a/Shared/mods/deathmatch/logic/CScriptDebugging.cpp b/Shared/mods/deathmatch/logic/CScriptDebugging.cpp index d30f7f2688a..c756db3da2b 100644 --- a/Shared/mods/deathmatch/logic/CScriptDebugging.cpp +++ b/Shared/mods/deathmatch/logic/CScriptDebugging.cpp @@ -10,6 +10,7 @@ *****************************************************************************/ #include "StdInc.h" +#include #define MAX_STRING_LENGTH 2048 @@ -224,9 +225,9 @@ void CScriptDebugging::LogString(const char* szPrePend, const SLuaDebugInfo& lua // Call on(Client)DebugMessage #ifdef MTA_CLIENT - notCancelled = g_pClientGame->GetRootEntity()->CallEvent("onClientDebugMessage", Arguments, false); + notCancelled = g_pClientGame->GetRootEntity()->CallEvent(BuiltInEvents::onClientDebugMessage, Arguments, false); #else - notCancelled = g_pGame->GetMapManager()->GetRootElement()->CallEvent("onDebugMessage", Arguments); + notCancelled = g_pGame->GetMapManager()->GetRootElement()->CallEvent(BuiltInEvents::onDebugMessage, Arguments); #endif // Reset trigger state, so onDebugMessage can be called again at a later moment diff --git a/Shared/mods/deathmatch/logic/event/BuiltInEvents.cpp b/Shared/mods/deathmatch/logic/event/BuiltInEvents.cpp new file mode 100644 index 00000000000..b3fd887d9e4 --- /dev/null +++ b/Shared/mods/deathmatch/logic/event/BuiltInEvents.cpp @@ -0,0 +1,27 @@ +#include + +#include "BuiltInEvents.h" +#include "BuiltInEventsListMacroApply.h" + +const BuiltInEvent* BuiltInEvent::Get(BuiltInEvent::ID id) +{ + #define CASE(name, _id) case BUILTINEVENT_ID_EXPAND(_id): return &BuiltInEvents::name; + + switch (id) + { + BUILTINEVENT_LIST_APPLY_MACRO(CASE) + default: + return nullptr; // This should never be hit + } +} + +const BuiltInEvent* BuiltInEvent::Get(const std::string& name) +{ + #define KVPAIR(name, id) {#name, &BuiltInEvents::name}, + static const std::unordered_map events = { + BUILTINEVENT_LIST_APPLY_MACRO(KVPAIR) + }; + if (auto it = events.find(name); it != events.end()) + return it->second; + return nullptr; +} diff --git a/Shared/mods/deathmatch/logic/event/BuiltInEvents.h b/Shared/mods/deathmatch/logic/event/BuiltInEvents.h new file mode 100644 index 00000000000..f3098e13ae0 --- /dev/null +++ b/Shared/mods/deathmatch/logic/event/BuiltInEvents.h @@ -0,0 +1,21 @@ +#pragma once + +#include "Event.h" +#include "BuiltInEventsListMacroApply.h" + +// How to add a new event: Go to BuiltInEventsListMacroApply.h + +class BuiltInEvents +{ +public: + // These variables have external linkage, so their addresses are the same across all TUs(.cpp files) + // This makes it possible to use their address (eg.: Event*) as the key to hash maps +#define DECLARE_EVENT(name, id) inline static const BuiltInEvent name{#name, BUILTINEVENT_ID_EXPAND(id)}; + BUILTINEVENT_LIST_APPLY_MACRO(DECLARE_EVENT) +#undef DECLARE_EVENT + + inline static constexpr auto COUNT{ static_cast(BuiltInEvent::ID::COUNT) }; +}; + +#undef BUILTINEVENT_LIST_APPLY_MACRO +#undef BUILTINEVENT_ID_EXPAND diff --git a/Shared/mods/deathmatch/logic/event/BuiltInEventsListMacroApply.h b/Shared/mods/deathmatch/logic/event/BuiltInEventsListMacroApply.h new file mode 100644 index 00000000000..417cbe9c8f9 --- /dev/null +++ b/Shared/mods/deathmatch/logic/event/BuiltInEventsListMacroApply.h @@ -0,0 +1,300 @@ +// How to add a new event: +// Just add it to BUILTINEVENT_LIST_APPLY_MACRO + +// Sorry for the macro of doom stuff, but than copy pasting it 5 times + +// Macro of doom: Calls macro with arguments as seen below. +// # can be used on the first argument to form a string. See code for examples in BuiltInEvents.h/cpp + +// Give special attention to the name, it must start with a lowercase letter! +#define BUILTINEVENT_ID_EXPAND(id) BuiltInEvent::ID::id +#ifdef MTA_CLIENT +#define BUILTINEVENT_LIST_APPLY_MACRO(macro) \ + /* Resource events */ \ + macro(onClientResourceStart, ON_CLIENT_RESOURCE_START) \ + macro(onClientResourceStop, ON_CLIENT_RESOURCE_STOP) \ + \ + /* Element events */ \ + macro(onClientElementDataChange, ON_CLIENT_ELEMENT_DATA_CHANGE) \ + macro(onClientElementStreamIn, ON_CLIENT_ELEMENT_STREAM_IN) \ + macro(onClientElementStreamOut, ON_CLIENT_ELEMENT_STREAM_OUT) \ + macro(onClientElementDestroy, ON_CLIENT_ELEMENT_DESTROY) \ + macro(onClientElementModelChange, ON_CLIENT_ELEMENT_MODEL_CHANGE) \ + macro(onClientElementDimensionChange, ON_CLIENT_ELEMENT_DIMENSION_CHANGE) \ + macro(onClientElementInteriorChange, ON_CLIENT_ELEMENT_INTERIOR_CHANGE) \ + \ + /* Player events */ \ + macro(onClientPlayerJoin, ON_CLIENT_PLAYER_JOIN) \ + macro(onClientPlayerQuit, ON_CLIENT_PLAYER_QUIT) \ + macro(onClientPlayerTarget, ON_CLIENT_PLAYER_TARGET) \ + macro(onClientPlayerSpawn, ON_CLIENT_PLAYER_SPAWN) \ + macro(onClientPlayerChangeNick, ON_CLIENT_PLAYER_CHANGE_NICK) \ + macro(onClientPlayerVehicleEnter, ON_CLIENT_PLAYER_VEHICLE_ENTER) \ + macro(onClientPlayerVehicleExit, ON_CLIENT_PLAYER_VEHICLE_EXIT) \ + macro(onClientPlayerTask, ON_CLIENT_PLAYER_TASK) \ + macro(onClientPlayerWeaponSwitch, ON_CLIENT_PLAYER_WEAPON_SWITCH) \ + macro(onClientPlayerStuntStart, ON_CLIENT_PLAYER_STUNT_START) \ + macro(onClientPlayerStuntFinish, ON_CLIENT_PLAYER_STUNT_FINISH) \ + macro(onClientPlayerRadioSwitch, ON_CLIENT_PLAYER_RADIO_SWITCH) \ + macro(onClientPlayerDamage, ON_CLIENT_PLAYER_DAMAGE) \ + macro(onClientPlayerWeaponFire, ON_CLIENT_PLAYER_WEAPON_FIRE) \ + macro(onClientPlayerWasted, ON_CLIENT_PLAYER_WASTED) \ + macro(onClientPlayerChoke, ON_CLIENT_PLAYER_CHOKE) \ + macro(onClientPlayerVoiceStart, ON_CLIENT_PLAYER_VOICE_START) \ + macro(onClientPlayerVoiceStop, ON_CLIENT_PLAYER_VOICE_STOP) \ + macro(onClientPlayerVoicePause, ON_CLIENT_PLAYER_VOICE_PAUSE) \ + macro(onClientPlayerVoiceResumed, ON_CLIENT_PLAYER_VOICE_RESUMED) \ + macro(onClientPlayerStealthKill, ON_CLIENT_PLAYER_STEALTH_KILL) \ + macro(onClientPlayerHitByWaterCannon, ON_CLIENT_PLAYER_HIT_BY_WATER_CANNON) \ + macro(onClientPlayerHeliKilled, ON_CLIENT_PLAYER_HELI_KILLED) \ + macro(onClientPlayerPickupHit, ON_CLIENT_PLAYER_PICKUP_HIT) \ + macro(onClientPlayerPickupLeave, ON_CLIENT_PLAYER_PICKUP_LEAVE) \ + macro(onClientPlayerNetworkStatus, ON_CLIENT_PLAYER_NETWORK_STATUS) \ + \ + /* Ped events */ \ + macro(onClientPedDamage, ON_CLIENT_PED_DAMAGE) \ + macro(onClientPedVehicleEnter, ON_CLIENT_PED_VEHICLE_ENTER) \ + macro(onClientPedVehicleExit, ON_CLIENT_PED_VEHICLE_EXIT) \ + macro(onClientPedWeaponFire, ON_CLIENT_PED_WEAPON_FIRE) \ + macro(onClientPedWasted, ON_CLIENT_PED_WASTED) \ + macro(onClientPedChoke, ON_CLIENT_PED_CHOKE) \ + macro(onClientPedHeliKilled, ON_CLIENT_PED_HELI_KILLED) \ + macro(onClientPedHitByWaterCannon, ON_CLIENT_PED_HIT_BY_WATER_CANNON) \ + macro(onClientPedStep, ON_CLIENT_PED_STEP) \ + \ + /* Vehicle events */ \ + macro(onClientVehicleRespawn, ON_CLIENT_VEHICLE_RESPAWN) \ + macro(onClientVehicleEnter, ON_CLIENT_VEHICLE_ENTER) \ + macro(onClientVehicleExit, ON_CLIENT_VEHICLE_EXIT) \ + macro(onClientVehicleStartEnter, ON_CLIENT_VEHICLE_START_ENTER) \ + macro(onClientVehicleStartExit, ON_CLIENT_VEHICLE_START_EXIT) \ + macro(onClientTrailerAttach, ON_CLIENT_TRAILER_ATTACH) \ + macro(onClientTrailerDetach, ON_CLIENT_TRAILER_DETACH) \ + macro(onClientVehicleExplode, ON_CLIENT_VEHICLE_EXPLODE) \ + macro(onClientVehicleCollision, ON_CLIENT_VEHICLE_COLLISION) \ + macro(onClientVehicleDamage, ON_CLIENT_VEHICLE_DAMAGE) \ + macro(onClientVehicleNitroStateChange, ON_CLIENT_VEHICLE_NITRO_STATE_CHANGE) \ + macro(onClientVehicleWeaponHit, ON_CLIENT_VEHICLE_WEAPON_HIT) \ + \ + /* GUI events */ \ + macro(onClientGUIClick, ON_CLIENT_GUI_CLICK) \ + macro(onClientGUIDoubleClick, ON_CLIENT_GUI_DOUBLE_CLICK) \ + macro(onClientGUIMouseDown, ON_CLIENT_GUI_MOUSE_DOWN) \ + macro(onClientGUIMouseUp, ON_CLIENT_GUI_MOUSE_UP) \ + macro(onClientGUIScroll, ON_CLIENT_GUI_SCROLL) \ + macro(onClientGUIChanged, ON_CLIENT_GUI_CHANGED) \ + macro(onClientGUIAccepted, ON_CLIENT_GUI_ACCEPTED) \ + macro(onClientGUITabSwitched, ON_CLIENT_GUI_TAB_SWITCHED) \ + macro(onClientGUIComboBoxAccepted, ON_CLIENT_GUI_COMBO_BOX_ACCEPTED) \ + \ + /* Input events */ \ + macro(onClientDoubleClick, ON_CLIENT_DOUBLE_CLICK) \ + macro(onClientMouseMove, ON_CLIENT_MOUSE_MOVE) \ + macro(onClientMouseEnter, ON_CLIENT_MOUSE_ENTER) \ + macro(onClientMouseLeave, ON_CLIENT_MOUSE_LEAVE) \ + macro(onClientMouseWheel, ON_CLIENT_MOUSE_WHEEL) \ + macro(onClientGUIMove, ON_CLIENT_GUI_MOVE) \ + macro(onClientGUISize, ON_CLIENT_GUI_SIZE) \ + macro(onClientGUIFocus, ON_CLIENT_GUI_FOCUS) \ + macro(onClientGUIBlur, ON_CLIENT_GUI_BLUR) \ + macro(onClientKey, ON_CLIENT_KEY) \ + macro(onClientCharacter, ON_CLIENT_CHARACTER) \ + macro(onClientPaste, ON_CLIENT_PASTE) \ + \ + /* Console events */ \ + macro(onClientConsole, ON_CLIENT_CONSOLE) \ + \ + /* Chat events */ \ + macro(onClientChatMessage, ON_CLIENT_CHAT_MESSAGE) \ + \ + /* Debug events */ \ + macro(onClientDebugMessage, ON_CLIENT_DEBUG_MESSAGE) \ + \ + /* Game events */ \ + macro(onClientPreRender, ON_CLIENT_PRE_RENDER) \ + macro(onClientPedsProcessed, ON_CLIENT_PEDS_PROCESSED) \ + macro(onClientHUDRender, ON_CLIENT_H_U_D_RENDER) \ + macro(onClientRender, ON_CLIENT_RENDER) \ + macro(onClientMinimize, ON_CLIENT_MINIMIZE) \ + macro(onClientRestore, ON_CLIENT_RESTORE) \ + \ + /* Cursor events */ \ + macro(onClientClick, ON_CLIENT_CLICK) \ + macro(onClientCursorMove, ON_CLIENT_CURSOR_MOVE) \ + \ + /* Marker events */ \ + macro(onClientMarkerHit, ON_CLIENT_MARKER_HIT) \ + macro(onClientMarkerLeave, ON_CLIENT_MARKER_LEAVE) \ + \ + /* Marker events */ \ + macro(onClientPickupHit, ON_CLIENT_PICKUP_HIT) \ + macro(onClientPickupLeave, ON_CLIENT_PICKUP_LEAVE) \ + \ + /* Col-shape events */ \ + macro(onClientColShapeHit, ON_CLIENT_COL_SHAPE_HIT) \ + macro(onClientColShapeLeave, ON_CLIENT_COL_SHAPE_LEAVE) \ + macro(onClientElementColShapeHit, ON_CLIENT_ELEMENT_COL_SHAPE_HIT) \ + macro(onClientElementColShapeLeave, ON_CLIENT_ELEMENT_COL_SHAPE_LEAVE) \ + \ + /* Explosion events */ \ + macro(onClientExplosion, ON_CLIENT_EXPLOSION) \ + \ + /* Projectile events */ \ + macro(onClientProjectileCreation, ON_CLIENT_PROJECTILE_CREATION) \ + \ + /* Sound events */ \ + macro(onClientSoundStream, ON_CLIENT_SOUND_STREAM) \ + macro(onClientSoundFinishedDownload, ON_CLIENT_SOUND_FINISHED_DOWNLOAD) \ + macro(onClientSoundChangedMeta, ON_CLIENT_SOUND_CHANGED_META) \ + macro(onClientSoundStarted, ON_CLIENT_SOUND_STARTED) \ + macro(onClientSoundStopped, ON_CLIENT_SOUND_STOPPED) \ + macro(onClientSoundBeat, ON_CLIENT_SOUND_BEAT) \ + \ + /* Object events */ \ + macro(onClientObjectDamage, ON_CLIENT_OBJECT_DAMAGE) \ + macro(onClientObjectBreak, ON_CLIENT_OBJECT_BREAK) \ + macro(onClientObjectMoveStart, ON_CLIENT_OBJECT_MOVE_START) \ + macro(onClientObjectMoveStop, ON_CLIENT_OBJECT_MOVE_STOP) \ + \ + /* Web events */ \ + macro(onClientBrowserWhitelistChange, ON_CLIENT_BROWSER_WHITELIST_CHANGE) \ + macro(onClientBrowserCreated, ON_CLIENT_BROWSER_CREATED) \ + macro(onClientBrowserLoadingStart, ON_CLIENT_BROWSER_LOADING_START) \ + macro(onClientBrowserDocumentReady, ON_CLIENT_BROWSER_DOCUMENT_READY) \ + macro(onClientBrowserLoadingFailed, ON_CLIENT_BROWSER_LOADING_FAILED) \ + macro(onClientBrowserNavigate, ON_CLIENT_BROWSER_NAVIGATE) \ + macro(onClientBrowserPopup, ON_CLIENT_BROWSER_POPUP) \ + macro(onClientBrowserCursorChange, ON_CLIENT_BROWSER_CURSOR_CHANGE) \ + macro(onClientBrowserTooltip, ON_CLIENT_BROWSER_TOOLTIP) \ + macro(onClientBrowserInputFocusChanged, ON_CLIENT_BROWSER_INPUT_FOCUS_CHANGED) \ + macro(onClientBrowserResourceBlocked, ON_CLIENT_BROWSER_RESOURCE_BLOCKED) \ + \ + /* Misc events */ \ + macro(onClientFileDownloadComplete, ON_CLIENT_FILE_DOWNLOAD_COMPLETE) \ + \ + macro(onClientResourceFileDownload, ON_CLIENT_RESOURCE_FILE_DOWNLOAD) \ + macro(onClientTransferBoxProgressChange, ON_CLIENT_TRANSFER_BOX_PROGRESS_CHANGE) \ + macro(onClientTransferBoxVisibilityChange, ON_CLIENT_TRANSFER_BOX_VISIBILITY_CHANGE) \ + \ + macro(onClientWeaponFire, ON_CLIENT_WEAPON_FIRE) \ + \ + macro(onClientWorldSound, ON_CLIENT_WORLD_SOUND) +#else +#define BUILTINEVENT_LIST_APPLY_MACRO(macro) \ + /* Resource events */ \ + macro(onResourcePreStart, ON_RESOURCE_PRE_START) \ + macro(onResourceStart, ON_RESOURCE_START) \ + macro(onResourceStop, ON_RESOURCE_STOP) \ + macro(onResourceLoadStateChange, ON_RESOURCE_LOAD_STATE_CHANGE) \ + \ + /* Blip events */ \ + \ + /* Marker events */ \ + macro(onMarkerHit, ON_MARKER_HIT) \ + macro(onMarkerLeave, ON_MARKER_LEAVE) \ + \ + /* Voice events */ \ + macro(onPlayerVoiceStart, ON_PLAYER_VOICE_START) \ + macro(onPlayerVoiceStop, ON_PLAYER_VOICE_STOP) \ + \ + /* Object events */ \ + \ + /* Pickup events */ \ + macro(onPickupHit, ON_PICKUP_HIT) \ + macro(onPickupLeave, ON_PICKUP_LEAVE) \ + macro(onPickupUse, ON_PICKUP_USE) \ + macro(onPickupSpawn, ON_PICKUP_SPAWN) \ + \ + /* Player events */ \ + macro(onPlayerConnect, ON_PLAYER_CONNECT) \ + macro(onPlayerChat, ON_PLAYER_CHAT) \ + macro(onPlayerDamage, ON_PLAYER_DAMAGE) \ + macro(onPlayerVehicleEnter, ON_PLAYER_VEHICLE_ENTER) \ + macro(onPlayerVehicleExit, ON_PLAYER_VEHICLE_EXIT) \ + macro(onPlayerJoin, ON_PLAYER_JOIN) \ + macro(onPlayerQuit, ON_PLAYER_QUIT) \ + macro(onPlayerSpawn, ON_PLAYER_SPAWN) \ + macro(onPlayerTarget, ON_PLAYER_TARGET) \ + macro(onPlayerWasted, ON_PLAYER_WASTED) \ + macro(onPlayerWeaponSwitch, ON_PLAYER_WEAPON_SWITCH) \ + macro(onPlayerMarkerHit, ON_PLAYER_MARKER_HIT) \ + macro(onPlayerMarkerLeave, ON_PLAYER_MARKER_LEAVE) \ + macro(onPlayerPickupHit, ON_PLAYER_PICKUP_HIT) \ + macro(onPlayerPickupLeave, ON_PLAYER_PICKUP_LEAVE) \ + macro(onPlayerPickupUse, ON_PLAYER_PICKUP_USE) \ + macro(onPlayerClick, ON_PLAYER_CLICK) \ + macro(onPlayerContact, ON_PLAYER_CONTACT) \ + macro(onPlayerBan, ON_PLAYER_BAN) \ + macro(onPlayerLogin, ON_PLAYER_LOGIN) \ + macro(onPlayerLogout, ON_PLAYER_LOGOUT) \ + macro(onPlayerChangeNick, ON_PLAYER_CHANGE_NICK) \ + macro(onPlayerPrivateMessage, ON_PLAYER_PRIVATE_MESSAGE) \ + macro(onPlayerStealthKill, ON_PLAYER_STEALTH_KILL) \ + macro(onPlayerMute, ON_PLAYER_MUTE) \ + macro(onPlayerUnmute, ON_PLAYER_UNMUTE) \ + macro(onPlayerCommand, ON_PLAYER_COMMAND) \ + macro(onPlayerModInfo, ON_PLAYER_MOD_INFO) \ + macro(onPlayerACInfo, ON_PLAYER_A_C_INFO) \ + macro(onPlayerNetworkStatus, ON_PLAYER_NETWORK_STATUS) \ + macro(onPlayerScreenShot, ON_PLAYER_SCREEN_SHOT) \ + macro(onPlayerDiscordJoin, ON_PLAYER_DISCORD_JOIN) \ + \ + /* Ped events */ \ + macro(onPedVehicleEnter, ON_PED_VEHICLE_ENTER) \ + macro(onPedVehicleExit, ON_PED_VEHICLE_EXIT) \ + macro(onPedWasted, ON_PED_WASTED) \ + macro(onPedWeaponSwitch, ON_PED_WEAPON_SWITCH) \ + \ + /* Element events */ \ + macro(onElementColShapeHit, ON_ELEMENT_COL_SHAPE_HIT) \ + macro(onElementColShapeLeave, ON_ELEMENT_COL_SHAPE_LEAVE) \ + macro(onElementClicked, ON_ELEMENT_CLICKED) \ + macro(onElementDataChange, ON_ELEMENT_DATA_CHANGE) \ + macro(onElementDestroy, ON_ELEMENT_DESTROY) \ + macro(onElementStartSync, ON_ELEMENT_START_SYNC) \ + macro(onElementStopSync, ON_ELEMENT_STOP_SYNC) \ + macro(onElementModelChange, ON_ELEMENT_MODEL_CHANGE) \ + macro(onElementDimensionChange, ON_ELEMENT_DIMENSION_CHANGE) \ + macro(onElementInteriorChange, ON_ELEMENT_INTERIOR_CHANGE) \ + \ + /* Radar area events */ \ + \ + /* Shape events */ \ + macro(onColShapeHit, ON_COL_SHAPE_HIT) \ + macro(onColShapeLeave, ON_COL_SHAPE_LEAVE) \ + \ + /* Vehicle events */ \ + macro(onVehicleDamage, ON_VEHICLE_DAMAGE) \ + macro(onVehicleRespawn, ON_VEHICLE_RESPAWN) \ + macro(onTrailerAttach, ON_TRAILER_ATTACH) \ + macro(onTrailerDetach, ON_TRAILER_DETACH) \ + macro(onVehicleStartEnter, ON_VEHICLE_START_ENTER) \ + macro(onVehicleStartExit, ON_VEHICLE_START_EXIT) \ + macro(onVehicleEnter, ON_VEHICLE_ENTER) \ + macro(onVehicleExit, ON_VEHICLE_EXIT) \ + macro(onVehicleExplode, ON_VEHICLE_EXPLODE) \ + \ + /* Console events */ \ + macro(onConsole, ON_CONSOLE) \ + \ + /* Debug events */ \ + macro(onDebugMessage, ON_DEBUG_MESSAGE) \ + \ + /* Ban events */ \ + macro(onBan, ON_BAN) \ + macro(onUnban, ON_UNBAN) \ + \ + /* Account events */ \ + macro(onAccountDataChange, ON_ACCOUNT_DATA_CHANGE) \ + \ + /* Other events */ \ + macro(onSettingChange, ON_SETTING_CHANGE) \ + macro(onChatMessage, ON_CHAT_MESSAGE) \ + \ + /* Weapon events */ \ + macro(onWeaponFire, ON_WEAPON_FIRE) \ + macro(onPlayerWeaponFire, ON_PLAYER_WEAPON_FIRE) +#endif +// ACHTUNG: DONT FORGET TO UNDEF THE MACROS IF YOU INCLUDE THIS FILE IN A HEADER + + diff --git a/Shared/mods/deathmatch/logic/event/CustomEvents.cpp b/Shared/mods/deathmatch/logic/event/CustomEvents.cpp new file mode 100644 index 00000000000..da55c45ce87 --- /dev/null +++ b/Shared/mods/deathmatch/logic/event/CustomEvents.cpp @@ -0,0 +1,20 @@ +#include +#include "CustomEvents.h" + +const CustomEvent* CustomEvent::Get(const std::string& name) +{ + return s_CustomEvents.Get(name); +} + +bool CustomEvent::Add(std::string name, CLuaMain* lmain, bool allowRemoteTrigger) +{ + return s_CustomEvents.Add(std::move(name), lmain, allowRemoteTrigger); +} + +void CustomEvents::OnEventRemove(const CustomEvent& event) +{ + // Remove all refs to this event + SPECIFIC_CODE(g_pClientGame->GetRootEntity(), g_pGame->GetMapManager()->GetRootElement())->IterChildren([&](CElement* elem) { + elem->GetEventHandlerCallDispatcher().Remove(event); + }); +} diff --git a/Shared/mods/deathmatch/logic/event/CustomEvents.h b/Shared/mods/deathmatch/logic/event/CustomEvents.h new file mode 100644 index 00000000000..01403a8d977 --- /dev/null +++ b/Shared/mods/deathmatch/logic/event/CustomEvents.h @@ -0,0 +1,90 @@ +#pragma once + +#include "Event.h" + +#include +#include +#include +#include + +class CLuaMain; + +// Handles `CustomEvent`s only +// For built-in events see namespace `BuiltInEvents` +// This class manages the lifetime of `CustomEvent`'s. +// You can create CustomEvent's here, get them by name, etc.. +class CustomEvents +{ +public: + // TODO: Implement CustomEventIDArray so we can eliminate the need of + // always using Event* => HandlerCollection + + // TODO: Fix name inconsistency (we clamp name length in `Add` but nowhere else) + // Maybe move this crap to API side + + const CustomEvent* Get(const std::string& name) + { + if (auto it = m_events.find(name); it != m_events.end()) + return it->second.get(); + return nullptr; + } + + bool Exists(const std::string& name) { return Get(name); } + + template + bool Add(std::string name, Ts&&... ts) + { + if (BuiltInEvent::Get(name)) // Can't register a built in event + return false; + // TODO: maybe move this string resize stuff to the API side? + if (name.length() > MAX_EVENT_NAME_LENGTH) + name.resize(MAX_EVENT_NAME_LENGTH); + if (auto [it, success] = m_events.emplace(name, nullptr); success) + { + it->second.reset(new CustomEvent(std::move(name), std::forward(ts)...)); // Can't use make_unique because `CustomEvent`'s constructor is `protected` + return true; + } + return false; + } + + // If you decide to add removeEvent function to the API + // remember that it might be called mid event iteration + // and if you delete the event object it will crash + // you will have to store the delete state, and also + // check if the event is being delete in the EventHandlerCollection call loop + // if it is, then stop the event iteration, and delte it + //bool Remove(const std::string& event) { return m_events.erase(event); } + + // tl;dr; we dont have to worry about events getting deleted while they're in use + // because resource stops are queued up and executed end frame + void RemoveAllOf(CLuaMain* owner) + { + for (auto it = m_events.begin(); it != m_events.end();) + { + if (it->second->GetCreatedBy() == owner) + { + OnEventRemove(*it->second); + it = m_events.erase(it); + } + else + it++; + } + } + +#ifdef MTA_CLIENT + // Should only be called from CClientGame + // It probably isn't needed as on reconnects the dll is unloaded + void Clear() { m_events.clear(); } +#endif +protected: + void OnEventRemove(const CustomEvent& event); + + // Since Event objects are interned we must ensure their addresses never change + // so we must use unique_ptr here. + // TODO: Or std::map without unique_ptr + std::unordered_map> m_events; +}; + +// This variable has external linkage, thus it must be the same object across all TUs (.cpp file) +// TODO: Maybe move this to CGame / CClientGame +inline CustomEvents s_CustomEvents{}; diff --git a/Shared/mods/deathmatch/logic/event/Event.cpp b/Shared/mods/deathmatch/logic/event/Event.cpp new file mode 100644 index 00000000000..8228837846b --- /dev/null +++ b/Shared/mods/deathmatch/logic/event/Event.cpp @@ -0,0 +1,10 @@ +#include +#include "CustomEvents.h" + +const Event* Event::Get(const std::string& name) +{ + dassert(!CustomEvent::Get(name) || !BuiltInEvent::Get(name)); // Event with the same name can't "exist twice" + if (auto* custom = CustomEvent::Get(name)) + return custom; + return BuiltInEvent::Get(name); +} diff --git a/Shared/mods/deathmatch/logic/event/Event.h b/Shared/mods/deathmatch/logic/event/Event.h new file mode 100644 index 00000000000..1f553f13658 --- /dev/null +++ b/Shared/mods/deathmatch/logic/event/Event.h @@ -0,0 +1,98 @@ +#pragma once + +#include +#include +#include + +#include "BuiltInEventsListMacroApply.h" +#include + +class CLuaMain; + +// Virtual base class +class Event +{ +public: + virtual ~Event() = default; + + virtual bool IsBuiltIn() const = 0; + + const std::string& GetName() const { return m_name; } + + static const Event* Get(const std::string& name); +protected: + Event(std::string name) : + m_name(std::move(name)) + { + } +private: + std::string m_name; +}; + +// Built-in-events defined in BuiltInEvents.h +class BuiltInEvent final : public Event +{ + friend class BuiltInEvents; +public: + + enum class ID + { + #define ENUM_DEFINE(name, enumName) enumName, + BUILTINEVENT_LIST_APPLY_MACRO(ENUM_DEFINE) + #undef ENUM_DECL + #undef BUILTINEVENT_ID_EXPAND + #undef BUILTINEVENT_LIST_APPLY_MACRO + + COUNT + }; + + virtual bool IsBuiltIn() const override { return true; } + ID GetID() const { return m_id; } + +#ifdef MTA_CLIENT + bool AllowAspectRatioAdjustment() const + { + return m_id == ID::ON_CLIENT_PRE_RENDER || m_id == ID::ON_CLIENT_RENDER || m_id == ID::ON_CLIENT_H_U_D_RENDER; + } +#endif + + // Wrappers around BuiltInEvents::Get + static const BuiltInEvent* Get(const std::string& name); + static const BuiltInEvent* Get(BuiltInEvent::ID id); // Intended for API uses only. To access a builtin event, just use BuiltInEvents +protected: + // Only BuiltInEvents is allowed to construct + BuiltInEvent(std::string name, ID id) : + Event(std::move(name)), + m_id(id) + { + } +private: + ID m_id; + +}; + +class CustomEvent final : public Event +{ + friend class CustomEvents; // Allow usage of constructor +public: + virtual bool IsBuiltIn() const override { return false; } + + auto GetCreatedBy() const { return m_createdBy; } + auto IsRemoteTriggerAllowed() const { return m_allowRemoteTrigger; } + + // Wrappers around CustomEvents::Add and Get + static const CustomEvent* Get(const std::string& name); + static bool Add(std::string name, CLuaMain* lmain, bool allowRemoteTrigger); +protected: + CustomEvent(std::string name, CLuaMain* createdBy, bool remoteTrigger) : + Event(std::move(name)), + m_createdBy(createdBy), + m_allowRemoteTrigger(remoteTrigger) + { + } +private: + CLuaMain* m_createdBy; // Where the event was registered in + bool m_allowRemoteTrigger; +}; + + diff --git a/Shared/mods/deathmatch/logic/event/EventDispatcher.cpp b/Shared/mods/deathmatch/logic/event/EventDispatcher.cpp new file mode 100644 index 00000000000..527640fe4a3 --- /dev/null +++ b/Shared/mods/deathmatch/logic/event/EventDispatcher.cpp @@ -0,0 +1,76 @@ +#include + +#include "EventDispatcher.h" +#include "Event.h" + +#include + +#ifdef MTA_CLIENT +#include +#else +#include +#include +#endif + +void EventDispatcher::PreEventPulse() +{ + m_cancelStack.push_back(m_eventCancelled); + m_eventCancelled = false; + m_wasEventCancelled = false; +} + +void EventDispatcher::PostEventPulse() +{ + m_wasEventCancelled = m_eventCancelled; + m_eventCancelled = m_cancelStack.back(); + m_cancelStack.pop_back(); +} + +void EventDispatcher::CancelEvent(bool cancelled, std::string reason) +{ + m_eventCancelled = cancelled; + m_cancelReason = std::move(reason); +} + +// Server/Client code compatibility crap +static auto GetGame() +{ +#ifdef MTA_CLIENT + return g_pClientGame; +#else + return g_pGame; +#endif +} + +bool EventDispatcher::Call(const Event& event, const CLuaArguments& args, bool callOnChildren, CElement* source SERVER_ONLY_ARG(CPlayer* client)) +{ + if (!GetGame()->GetDebugHookManager()->OnPreEvent(event.GetName(), args, source, SPECIFIC_CODE(nullptr, client))) + return false; + PreEventPulse(); + + CLIENT_ONLY(const auto timeBegin = GetTimeUs();) + + // Call all event handlers (us, ancestors, children) + { + const auto CallHandlers = [&](auto* elem) { + elem->GetEventHandlerCallDispatcher().Emmit(event, args, source, elem SERVER_ONLY_ARG(client)); + }; + CallHandlers(source); + source->IterAncestors(CallHandlers); + if (callOnChildren) + source->IterChildren(CallHandlers); + } + + PostEventPulse(); +#ifdef MTA_CLIENT + if (IS_TIMING_CHECKPOINTS()) + { + TIMEUS deltaTimeUs = GetTimeUs() - timeBegin; + if (deltaTimeUs > 10000) + TIMING_DETAIL(SString("Event: %s [%d ms]", event.GetName().c_str(), deltaTimeUs / 1000)); + } +#endif + GetGame()->GetDebugHookManager()->OnPostEvent(event.GetName(), args, source, SPECIFIC_CODE(nullptr, client)); + + return !WasEventCancelled(); +} diff --git a/Shared/mods/deathmatch/logic/event/EventDispatcher.h b/Shared/mods/deathmatch/logic/event/EventDispatcher.h new file mode 100644 index 00000000000..8ff20b31b5c --- /dev/null +++ b/Shared/mods/deathmatch/logic/event/EventDispatcher.h @@ -0,0 +1,31 @@ +#pragma once +#include +#include +#include + +class Event; +class CLuaArguments; +class CElement; +class CPlayer; + +class EventDispatcher +{ +public: + bool Call(const Event& event, const CLuaArguments& args, bool callOnChildren, CElement* source SERVER_ONLY_ARG(CPlayer* client)); + + void PreEventPulse(); + void PostEventPulse(); + + void CancelEvent(bool cancelled) { m_eventCancelled = cancelled; } + void CancelEvent(bool cancelled, std::string reason); + bool WasEventCancelled() const { return m_wasEventCancelled; } + + const std::string& GetCancelReason() const { return m_cancelReason; } +protected: + bool m_eventCancelled = false; + bool m_wasEventCancelled = false; + std::vector m_cancelStack; + std::string m_cancelReason; +}; + +static inline EventDispatcher s_EventDispatcher; diff --git a/Shared/mods/deathmatch/logic/event/EventHandler.cpp b/Shared/mods/deathmatch/logic/event/EventHandler.cpp new file mode 100644 index 00000000000..df0db8cfc42 --- /dev/null +++ b/Shared/mods/deathmatch/logic/event/EventHandler.cpp @@ -0,0 +1,185 @@ +#include +#ifdef MTA_CLIENT +bool g_bAllowAspectRatioAdjustment = false; +#endif + +#include "EventHandler.h" +#include "Event.h" + +#include +#include + +#include +#include +#include + + +// Server/Client code compatibility crap +auto GetGame() +{ +#ifdef MTA_CLIENT + return g_pClientGame; +#else + return g_pGame; +#endif +} + +// Parse strings in format <[+-]modifier>. Eg.: +// Value | Priority | Modifier +// low+1 | low | 1 +// high+1 | high | 1 +// high+ | high | 0 (atof retruns 0) +// high- | high | same as above +// +1 | error | error +// high | high | 0 +EventHandler::Priority::Priority(std::string_view value) +{ + if (value.empty()) + return; // Variables are initalized at this to default values + + std::string_view priority = value; + if (auto at = value.find_first_of("+-"); at != std::string_view::npos) // find +- + { + if (at == 0) + throw std::invalid_argument("Missing priority level in priority string"); + + // Parse modifier + m_mod = std::stof(std::string{value.substr(at)}); // TODO: replace this with from_chars when GCC is updated from 10.2 + // NOTE: from_chars might fail, in which case m_mod remains 0.0f + // Ideally we would throw here but we have to remain backwards compatible. + + priority = value.substr(0, at); + } + if (!StringToEnum(std::string{priority}, m_lvl)) // TODO: Use std::less<> in StringToEnum map, thus enabling transparent lookup + throw std::invalid_argument("Unknown priority level"); // TODO(C++20): Include string with std::format +} + +std::string EventHandler::Priority::ToString() const +{ + return SString("%s%+f", EnumToString(m_lvl).c_str(), m_mod); +} + +IMPLEMENT_ENUM_CLASS_BEGIN(EventHandler::Priority::Level) +ADD_ENUM(EventHandler::Priority::Level::LOW, "low") +ADD_ENUM(EventHandler::Priority::Level::NORMAL, "normal") +ADD_ENUM(EventHandler::Priority::Level::HIGH, "high") +IMPLEMENT_ENUM_CLASS_END("EventHandlerPriority") + + +void EventHandler::operator()(const Event& event, const CLuaArguments& args, CElement* source, CElement* us SERVER_ONLY_ARG(CPlayer* client)) +{ + if (!m_handlesPropagated && source != us) + return; + + const auto timeBeginUS = GetTimeUs(); + +#ifdef MTA_CLIENT + const bool allowAspectRatioAdjustment = event.IsBuiltIn() && static_cast(event).AllowAspectRatioAdjustment(); + if (allowAspectRatioAdjustment) + { + g_bAllowAspectRatioAdjustment = true; + using namespace std::string_view_literals; + if (m_lmain->GetScriptName() == "customblips"sv) // customblips resource forces aspect ratio on + { + g_pCore->GetGraphics()->SetAspectRatioAdjustmentEnabled(true); + } + } + + static bool bEnabled = (g_pCore->GetDiagnosticDebug() == EDiagnosticDebug::LUA_TRACE_0000); + if (bEnabled) + g_pCore->LogEvent(0, "Lua Event", m_lmain->GetScriptName(), event.GetName().c_str()); +#endif + + if (!GetGame()->GetDebugHookManager()->OnPreEventFunction(event.GetName(), args, source, SPECIFIC_CODE(nullptr, client), *this)) + return; + + const bool wasDeletable = m_canBeDeleted; + m_canBeDeleted = false; // Keep this object alive (Lua callback could call removeEventHandler) + + lua_State* L = GetLuaMain()->GetVM(); + LUA_CHECKSTACK(L, 1); + LUA_STACK_EXPECT(0); + +#ifdef MTA_CLIENT + using CPerfStatLuaTiming = CClientPerfStatLuaTiming; +#endif + + if (m_lmain) // As per old code.. Pretty sure this can never happen + { + // Call event handler with our wrapper function + // the wrapper function is responsible for setting and restoring globals + // see it's source code in EmbedLuaCode::DispatchEvent + + const int preCallTop = lua_gettop(L); + + const auto PushFn = [L](int ref) { + lua_getref(L, ref); + assert(lua_type(L, -1) == LUA_TFUNCTION); + }; + // Based on code from CLuaArguments::Call + + PushFn(m_lmain->GetDispatchEventFnRef()); // Push wrapper + + // Push wrapper args + PushFn(m_fn.ToInt()); // handlerfn + lua::Push(L, source); // source + lua::Push(L, us); // this + SERVER_ONLY(lua::Push(L, client);) // client (server only) + + // sourceResource and sourceResourceRoot + if (auto topLuaMain = GetGame()->GetScriptDebugging()->GetTopLuaMain()) + { + auto sourceResource = topLuaMain->GetResource(); + lua::Push(L, sourceResource); + #ifdef MTA_CLIENT + lua::Push(L, sourceResource->GetResourceDynamicEntity()); + #else + lua::Push(L, sourceResource->GetResourceRootElement()); + #endif + } + else + { + lua::Push(L, nullptr); + lua::Push(L, nullptr); + } + + lua::Push(L, event.GetName()); // eventName + args.PushArguments(L); // push handler variadic fn args + + m_lmain->ResetInstructionCount(); + + #ifdef MTA_CLIENT + switch (m_lmain->PCall(L, 6 + args.Count(), 0, 0)) // 6 args for wrapper + variadic (args.Count()) + #else + switch (m_lmain->PCall(L, 7 + args.Count(), 0, 0)) // 7 args for wrapper + variadic (args.Count()) + #endif + { + case LUA_ERRRUN: + case LUA_ERRMEM: + { + GetGame()->GetScriptDebugging()->LogPCallError(L, ConformResourcePath(lua_tostring(L, -1))); + break; + } + default: + { + // Record timing of this function call + CPerfStatLuaTiming::GetSingleton()->UpdateLuaTiming(m_lmain, m_lmain->GetFunctionTag(m_fn.ToInt()), GetTimeUs() - timeBeginUS); + } + } + lua_settop(L, preCallTop); + } + +#ifdef MTA_CLIENT + if (allowAspectRatioAdjustment) + { + g_pCore->GetGraphics()->SetAspectRatioAdjustmentEnabled(false); + g_bAllowAspectRatioAdjustment = false; + } +#endif + + // Record timing of this event (separatly from the function call) + CPerfStatLuaTiming::GetSingleton()->UpdateLuaTiming(m_lmain, event.GetName().c_str(), GetTimeUs() - timeBeginUS); + + GetGame()->GetDebugHookManager()->OnPostEventFunction(event.GetName(), args, source, SPECIFIC_CODE(nullptr, client), *this); + m_canBeDeleted = wasDeletable; +} diff --git a/Shared/mods/deathmatch/logic/event/EventHandler.h b/Shared/mods/deathmatch/logic/event/EventHandler.h new file mode 100644 index 00000000000..0c7302ea8bb --- /dev/null +++ b/Shared/mods/deathmatch/logic/event/EventHandler.h @@ -0,0 +1,101 @@ +#pragma once +#include +#include +#include +#include + +class CLuaMain; +class CPlayer; +class CElement; +class Event; +class CLuaArguments; + +class EventHandler +{ +// TODO Deal with CElement define at some point, and replace it with a `using CElement = CClientEntity` OR refactor CClientEntity to be CElement +#ifdef MTA_CLIENT +#ifndef CElement + using CElement = CClientEntity; +#endif +#endif + +public: + struct Priority + { + enum class Level + { + LOW, + NORMAL, + HIGH + }; + + Priority() = default; + Priority(std::string_view value); + Priority(Level l, float m) : m_lvl(l), m_mod(m) {} + + friend bool operator<(const Priority& l, const Priority& r) + { + if (l.m_lvl == r.m_lvl) + return l.m_mod < r.m_mod; // Same level, check modifiers + return l.m_lvl < r.m_lvl; + } + friend bool operator>(const Priority& l, const Priority& r) { return r < l; } + friend bool operator<=(const Priority& l, const Priority& r) { return !(l > r); } + friend bool operator>=(const Priority& l, const Priority& r) { return !(l < r); } + + friend bool operator==(const Priority& l, const Priority& r) { return std::tie(l.m_lvl, l.m_mod) == std::tie(r.m_lvl, r.m_mod); } + friend bool operator!=(const Priority& l, const Priority& r) { return !(l == r); } + + std::string ToString() const; + protected: + Level m_lvl = Level::LOW; + float m_mod = 0.0f; + }; + + EventHandler(Priority priority, CLuaMain* lmain, const CLuaFunctionRef& fn, bool handlePropagated) : + m_priority(priority), + m_lmain(lmain), + m_fn(fn), + m_handlesPropagated(handlePropagated) + { + } + + CLuaMain* GetLuaMain() const { return m_lmain; } + const auto& GetCallback() const { return m_fn; } + + const auto& GetPriority() const { return m_priority; } + + void operator()(const Event& event, const CLuaArguments& args, CElement* source, CElement* us SERVER_ONLY_ARG(CPlayer* client)); + //bool CanBeCalled() const { return !IsBeingDeleted(); } TODO: Add check if m_fn is valid (VERIFY_FUNCTION) + + void SetListRev(size_t rev) { m_listRevWhenInserted = rev; } + size_t GetListRev() const { return m_listRevWhenInserted; } + + friend bool operator==(const EventHandler& l, const EventHandler& r) + { + const auto GetTie = [](const EventHandler& h) { + return std::tie(h.m_priority, h.m_lmain, h.m_fn, h.m_handlesPropagated); + }; + return GetTie(l) == GetTie(r); + } + friend bool operator!=(const EventHandler& l, const EventHandler& r) { return !(l == r); } + + void DoMarkToBeDeleted() { m_markedToBeDeleted = true; } + bool IsMarkedToBeDeleted() const { return m_markedToBeDeleted; } + + bool CanBeDeleted() const { return m_canBeDeleted; } +protected: + Priority m_priority{}; + + CLuaMain* m_lmain = nullptr; + CLuaFunctionRef m_fn{}; + + size_t m_listRevWhenInserted = 0; + + bool m_handlesPropagated = false; + + bool m_canBeDeleted = true; + bool m_markedToBeDeleted = false; +}; + +DECLARE_ENUM_CLASS(EventHandler::Priority::Level); diff --git a/Shared/mods/deathmatch/logic/event/EventHandlerCallDispatcher.cpp b/Shared/mods/deathmatch/logic/event/EventHandlerCallDispatcher.cpp new file mode 100644 index 00000000000..29934b97263 --- /dev/null +++ b/Shared/mods/deathmatch/logic/event/EventHandlerCallDispatcher.cpp @@ -0,0 +1,53 @@ +#include + +#include "EventHandlerCallDispatcher.h" +#include "EventHandlerCollection.h" +#include "Event.h" + +EventHandlerCollection* EventHandlerCallDispatcher::GetHandlers(const Event& event, bool allowCreate) +{ + if (event.IsBuiltIn()) + { + const auto& builtin = static_cast(event); + return &(*GetHandlers(builtin)); + } + else + { + const auto& custom = static_cast(event); + if (allowCreate) + return &m_custom[&custom]; // operator[] will construct object if not in map + else + { + if (auto [it, success] = GetHandlers(custom); success) + return &it->second; + return nullptr; + } + } +} + +bool EventHandlerCallDispatcher::Remove(const Event& event, CLuaMain* lmain, const CLuaFunctionRef& fn) +{ + if (auto handlers = GetHandlers(event); handlers) + return handlers->Remove(lmain, fn); + return false; +} + +void EventHandlerCallDispatcher::Remove(CLuaMain* lmain) +{ + ForAll([lmain](EventHandlerCollection& c) { + c.Remove(lmain); + }); +} + +void EventHandlerCallDispatcher::Remove(const CustomEvent& event) +{ + if (auto [it, success] = GetHandlers(event); success) + m_custom.erase(it); +} + +void EventHandlerCallDispatcher::Clear() +{ + ForAll([](EventHandlerCollection& c) { + c.Clear(); + }); +} diff --git a/Shared/mods/deathmatch/logic/event/EventHandlerCallDispatcher.h b/Shared/mods/deathmatch/logic/event/EventHandlerCallDispatcher.h new file mode 100644 index 00000000000..cc12a1b6f20 --- /dev/null +++ b/Shared/mods/deathmatch/logic/event/EventHandlerCallDispatcher.h @@ -0,0 +1,71 @@ +#pragma once + +#include "BuiltInEvents.h" +#include "EventHandlerCollection.h" + +#include +#include +#include + +class CLuaMain; +class Event; +class CLuaFunctionRef; +class CustomEvent; +class BuiltInEvent; + +class EventHandlerCallDispatcher +{ +#ifdef MTA_CLIENT +#ifndef CElement + using CElement = CClientEntity; +#endif +#endif +public: + bool Remove(const Event& event, CLuaMain* lmain, const CLuaFunctionRef& fn); + + // This function is called to remove all handlers created by the given lmain. + // Note: In theory, it's never called while we're processing an event + // since resource stops are queued up, and executed at frame end + void Remove(CLuaMain* lmain); + + void Remove(const CustomEvent& event); + + template + void Emmit(const Event& event, Ts&&... ts) + { + if (auto handlers = GetHandlers(event)) + handlers->Emmit(event, std::forward(ts)...); + } + + auto Add(const Event& event, EventHandler handler) { return GetHandlers(event, true)->Add(handler); } + + EventHandlerCollection* GetHandlers(const Event& event, bool allowCreate = false); + + void Clear(); +protected: + + auto GetHandlers(const BuiltInEvent& event) + { + return std::next(m_builtins.begin(), static_cast(event.GetID())); + } + + auto GetHandlers(const CustomEvent& event) + { + if (auto it = m_custom.find(&event); it != m_custom.end()) + return std::make_pair(it, true); + return std::make_pair(m_custom.end(), false); + } + + template + void ForAll(Fn fn) + { + for (auto& c : m_builtins) + fn(c); + for (auto& [k, c] : m_custom) + fn(c); + } + + std::array m_builtins{}; + std::unordered_map m_custom; +}; + diff --git a/Shared/mods/deathmatch/logic/event/EventHandlerCollection.cpp b/Shared/mods/deathmatch/logic/event/EventHandlerCollection.cpp new file mode 100644 index 00000000000..e3163f54f9b --- /dev/null +++ b/Shared/mods/deathmatch/logic/event/EventHandlerCollection.cpp @@ -0,0 +1,100 @@ +#include + +#include "EventHandlerCollection.h" +#include + +bool EventHandlerCollection::Add(EventHandler handler) +{ + if (HandleExists(handler)) + return false; + + const auto whereIt = std::lower_bound(m_handlers.begin(), m_handlers.end(), handler.GetPriority(), + [](const auto& handler, const auto& priority) { + return handler.GetPriority() > priority; + } + ); + const auto emplacedIt = m_handlers.emplace(whereIt, std::move(handler)); + emplacedIt->SetListRev(++m_listRev); + return true; +} + +bool EventHandlerCollection::Remove(CLuaMain* lmain, const CLuaFunctionRef& fn) +{ + return EraseIf([lmain, &fn](const EventHandler& h) { + return h.GetLuaMain() == lmain && h.GetCallback() == fn; + }); +} + +// See note in EventHandlerCallDispatcher::Remove(CLuaMain*) (caller of this function) +void EventHandlerCollection::Remove(CLuaMain* lmain) +{ + EraseIf([lmain](const EventHandler& h) { + return h.GetLuaMain() == lmain; + }, false); +} + +bool EventHandlerCollection::HandleExists(CLuaMain* lmain, const CLuaFunctionRef& fn) const +{ + return std::find_if(m_handlers.begin(), m_handlers.end(), [lmain, &fn](const EventHandler& h) { + return !h.IsMarkedToBeDeleted() && h.GetLuaMain() == lmain && h.GetCallback() == fn; + }) != m_handlers.end(); +} + +bool EventHandlerCollection::HandleExists(const EventHandler& toFind) const +{ + return std::find_if(m_handlers.begin(), m_handlers.end(), [&toFind](const EventHandler& h) { + return !h.IsMarkedToBeDeleted() && h == toFind; + }) != m_handlers.end(); +} + +void EventHandlerCollection::PushToLua(CLuaMain* lmain, lua_State* L) const +{ + int index = 1; + for (const auto& handler : m_handlers) + { + if (handler.GetLuaMain() != lmain) + continue; + if (handler.IsMarkedToBeDeleted()) + continue; + lua_getref(L, handler.GetCallback().ToInt()); + lua_rawseti(L, -2, index++); + } +} + +void EventHandlerCollection::Emmit(const Event& event, const CLuaArguments& args, CElement* sourceElement, CElement* thisElement SERVER_ONLY_ARG(CPlayer* client)) +{ + CLIENT_ONLY(std::string timingStats;) + CLIENT_ONLY(const auto emmitBeginUs = GetTimeUs();) + + const size_t listRev = m_listRev; + for (auto it = m_handlers.begin(); it != m_handlers.end(); + (it->IsMarkedToBeDeleted() && it->CanBeDeleted()) ? it = m_handlers.erase(it) : it++) + { + auto& handler = *it; + if (handler.IsMarkedToBeDeleted()) + continue; + if (handler.GetListRev() > listRev) // Was it after we've started iterating? + continue; // Yes, this can happen if a previously called handler added it + + #ifdef MTA_CLIENT + const auto handlerBeginUs = GetTimeUs(); + handler(event, args, sourceElement, thisElement); + if (IS_TIMING_CHECKPOINTS()) + { + if (auto delta = GetTimeUs() - handlerBeginUs; delta >= 3000) + timingStats += SString(" (%s %d ms)", handler.GetLuaMain()->GetScriptName(), delta / 1000); + } + #else + handler(event, args, sourceElement, thisElement, client); + #endif + } + +#ifdef MTA_CLIENT + if (IS_TIMING_CHECKPOINTS()) + { + TIMEUS deltaTimeUs = GetTimeUs() - emmitBeginUs; + if (deltaTimeUs > 5000) + TIMING_DETAIL(SString("EventHandlerCollection::Call ( %s, ... ) took %d ms ( %s )", event.GetName().c_str(), deltaTimeUs / 1000, timingStats.c_str())); + } +#endif +} diff --git a/Shared/mods/deathmatch/logic/event/EventHandlerCollection.h b/Shared/mods/deathmatch/logic/event/EventHandlerCollection.h new file mode 100644 index 00000000000..9202c7563db --- /dev/null +++ b/Shared/mods/deathmatch/logic/event/EventHandlerCollection.h @@ -0,0 +1,66 @@ +#pragma once + +#include "EventHandler.h" + +#include +#include + +class Event; +struct lua_State; + +// Collection of handler functions attached to the same event and element +class EventHandlerCollection +{ +#ifdef MTA_CLIENT +#ifndef CElement + using CElement = CClientEntity; +#endif +#endif +public: + bool Add(EventHandler handler); + + bool Remove(CLuaMain* lmain, const CLuaFunctionRef& fn); + void Remove(CLuaMain* lmain); + + bool HandleExists(CLuaMain* lmain, const CLuaFunctionRef& fn) const; + bool HandleExists(const EventHandler& toFind) const; + + void PushToLua(CLuaMain* lmain, lua_State* L) const; + bool Empty() const { return m_handlers.empty(); } + void Clear() { m_handlers.clear(); } + void Emmit(const Event& event, const CLuaArguments& args, CElement* sourceElement, CElement* thisElement SERVER_ONLY_ARG(CPlayer* client)); +protected: + template + bool EraseIf(Pred pred, bool checkCanBeDeleted = true) // Returns if any handlers were erased / marked to be erased(deleted) + { + bool anyMatched = false; + for (auto it = m_handlers.begin(); it != m_handlers.end();) + { + if (auto& handler = *it; pred(handler)) + { + anyMatched = true; + if (!checkCanBeDeleted || handler.CanBeDeleted()) + { + it = m_handlers.erase(it); + continue; // Skip it++ + } + else + handler.DoMarkToBeDeleted(); // Just mark it, don't erase it from the list yet as that may make us crash + } + it++; + } + return anyMatched; + } + + // With this we can track when a handler was added. + // Increased every time a handler is added. + size_t m_listRev = 0; + + // TODO: If performance is crap, maybe we could use some kind of object pool allocator for better data locality? + // NOTE: vector cant be used, because it invalidates iterators on reallocation (while we might be in the middle of iterating thru it) + // TODO: Somehow move the `to-be-deleted` handler out of the list, because this way there has to be checks for `IsMarkedToBeDeleted` + // + // ACHTUNG!!: This list might contain `to-be-deleted` handler(s). This happens when the handler calls removeEventHandler. + // + std::list m_handlers; +}; diff --git a/Shared/mods/deathmatch/logic/event/README.md b/Shared/mods/deathmatch/logic/event/README.md new file mode 100644 index 00000000000..19d99eb2560 --- /dev/null +++ b/Shared/mods/deathmatch/logic/event/README.md @@ -0,0 +1,23 @@ +#### `CustomEvent` and `BuiltInEvent` (Event.h): +All event objects are interned: This way we can use plain pointer comparasion to decide if two `Event`'s are the same +##### `CustomEvent` +Shepherd (factory) class is `CustomEventShepherd`. Represents an event created by the user. +##### `BuiltInEvent` +All built-in-events are defined in `BuiltInEvents.h`. Each object of this type has a unique `ID` assigned to it, this way we can eliminate the need of using hash maps for built-in events. + +#### EventDispatcher.h +It is responsible for calling the event handlers by traversing the element tree. +It also handles `CancelEvent()`. + +#### EventHandler +Basically a small wrapper around a `CLuaFunctionRef` with some additional bookkeeping stuff. + +#### EventHandlerCollection +A collection of handlers attached to the same event and element. + +#### EventHandlerCallDispatcher +A per-element "manager". It's main purpose is to deal with the `Event` => `EventHandlerCollection` mapping. +A side-note: As you might've seen, this class has 2 members: `m_customs` and `m_builtins`. `m_customs` should be quite obvious, but `m_builtins` might not be: It needs to be indexed with `BuiltInEvent::ID`. + + + diff --git a/Shared/mods/deathmatch/logic/luascripts/DispatchEvent.lua.h b/Shared/mods/deathmatch/logic/luascripts/DispatchEvent.lua.h new file mode 100644 index 00000000000..37204b56640 --- /dev/null +++ b/Shared/mods/deathmatch/logic/luascripts/DispatchEvent.lua.h @@ -0,0 +1,88 @@ +namespace EmbeddedLuaCode +{ + // Special function for calling event handlers + // We use a script because doing it in C++ is slower (and way more complex) + + // Client and server code only differ in the absence of the `client` argument (on client side) +#ifdef MTA_CLIENT + constexpr auto DispatchEvent = R"~LUA~( +function DispatchEvent(handlerfn, _source, _this, _sourceResource, _sourceResourceRoot, _eventName, ...) + --[[ + print("DispatchEvent with args:", inspect({ + handlerfn = handlerfn, + source = _source or "null", + this = _this or "null", + sourceResource = _sourceResource or "null", + sourceResourceRoot = _sourceResourceRoot or "null", + eventName = _eventName or "null", + })) + ]] + + -- save old globals + local oldSource = source + local oldThis = this + local oldSourceResource = sourceResource + local oldSourceResourceRoot = sourceResourceRoot + local oldEventName = eventName + + -- set globals of this event + source = _source + this = _this + sourceResource = _sourceResource + sourceResourceRoot = _sourceResourceRoot + eventName = _eventName + + handlerfn(...) + + -- restore globals + source = oldSource + this = oldThis + sourceResource = oldSourceResource + sourceResourceRoot = oldSourceResourceRoot + eventName = oldEventName +end + )~LUA~"; +#else + constexpr auto DispatchEvent = R"~LUA~( +function DispatchEvent(handlerfn, _source, _this, _client, _sourceResource, _sourceResourceRoot, _eventName, ...) + --[[ + print("DispatchEvent with args:", inspect({ + handlerfn = handlerfn, + source = _source or "null", + this = _this or "null", + client = _client or "null", + sourceResource = _sourceResource or "null", + sourceResourceRoot = _sourceResourceRoot or "null", + eventName = _eventName or "null", + })) + ]] + + -- save old globals + local oldSource = source + local oldThis = this + local oldClient = client + local oldSourceResource = sourceResource + local oldSourceResourceRoot = sourceResourceRoot + local oldEventName = eventName + + -- set globals of this event + source = _source + this = _this + client = _client + sourceResource = _sourceResource + sourceResourceRoot = _sourceResourceRoot + eventName = _eventName + + handlerfn(...) + + -- restore globals + source = oldSource + this = oldThis + client = oldClient + sourceResource = oldSourceResource + sourceResourceRoot = oldSourceResourceRoot + eventName = oldEventName +end + )~LUA~"; +#endif +}; diff --git a/Shared/sdk/SharedUtil.Template.h b/Shared/sdk/SharedUtil.Template.h index 1b138e54b12..51fe3230809 100644 --- a/Shared/sdk/SharedUtil.Template.h +++ b/Shared/sdk/SharedUtil.Template.h @@ -248,3 +248,21 @@ struct pad_func_with_func : pad_func_with_func_impl::type> { }; + + +// (hopefully) Quality of life macros +#ifdef MTA_CLIENT +#define SERVER_ONLY(code) +#define CLIENT_ONLY(code) code +#define CLIENT_ONLY_ARG(arg) ,arg +#define SERVER_ONLY_ARG(arg) +#define SPECIFIC_CODE(client, server) client +#else +#define CLIENT_ONLY(code) +#define SERVER_ONLY(code) code +#define SERVER_ONLY_ARG(arg) ,arg +#define CLIENT_ONLY_ARG(arg) +#define SPECIFIC_CODE(client, server) server +#endif + +// For the SERVER/CLIENT_ONLY macros don't forget to put the ; inside of the macro