Пример #1
0
void CLuaArguments::ReadTable(lua_State* luaVM, int iIndexBegin, CFastHashMap<const void*, CLuaArguments*>* pKnownTables)
{
    bool bKnownTablesCreated = false;
    if (!pKnownTables)
    {
        pKnownTables = new CFastHashMap<const void*, CLuaArguments*>();
        bKnownTablesCreated = true;
    }

    pKnownTables->insert(std::make_pair(lua_topointer(luaVM, iIndexBegin), this));

    // Delete the previous arguments if any
    DeleteArguments();

    LUA_CHECKSTACK(luaVM, 2);
    lua_pushnil(luaVM); /* first key */
    if (iIndexBegin < 0)
        iIndexBegin--;

    while (lua_next(luaVM, iIndexBegin) != 0)
    {
        /* uses 'key' (at index -2) and 'value' (at index -1) */
        CLuaArgument* pArgument = new CLuaArgument(luaVM, -2, pKnownTables);
        m_Arguments.push_back(pArgument);            // push the key first

        pArgument = new CLuaArgument(luaVM, -1, pKnownTables);
        m_Arguments.push_back(pArgument);            // then the value

        /* removes 'value'; keeps 'key' for next iteration */
        lua_pop(luaVM, 1);
    }

    if (bKnownTablesCreated)
        delete pKnownTables;
}
Пример #2
0
bool CLuaArguments::CallGlobal ( CLuaMain* pLuaMain, const char* szFunction, CLuaArguments * returnValues ) const
{
    assert ( pLuaMain );
    assert ( szFunction );
    TIMEUS startTime = GetTimeUs ();

    // Add the function name to the stack and get the event from the table
    lua_State* luaVM = pLuaMain->GetVirtualMachine ();
    assert ( luaVM );
    LUA_CHECKSTACK ( luaVM, 1 );
    int luaStackPointer = lua_gettop ( luaVM );
    lua_pushstring ( luaVM, szFunction );
    lua_gettable ( luaVM, LUA_GLOBALSINDEX );

    // Push our arguments onto the stack
    PushArguments ( luaVM );

    // Call the function with our arguments
    pLuaMain->ResetInstructionCount ();
    int iret = 0;
    try {
        iret = lua_pcall ( luaVM, m_Arguments.size (), LUA_MULTRET, 0 );
    }
    catch ( ... )
    {
        return false;
    }
    if ( iret == LUA_ERRRUN || iret == LUA_ERRMEM )
    {
        std::string strRes = ConformResourcePath ( lua_tostring( luaVM, -1 ) );
        g_pGame->GetScriptDebugging()->LogError ( luaVM, "%s", strRes.c_str () );

        // cleanup the stack
        while ( lua_gettop ( luaVM ) - luaStackPointer > 0 )
            lua_pop ( luaVM, 1 );

        return false; // the function call failed
    }
    else
    {
        int iReturns = lua_gettop ( luaVM ) - luaStackPointer;

        if ( returnValues != NULL )
        {
            for ( int i = - iReturns; i <= -1; i++ )
            {
                returnValues->ReadArgument ( luaVM, i );
            }
        }

        // cleanup the stack
        while ( lua_gettop ( luaVM ) - luaStackPointer > 0 )
            lua_pop ( luaVM, 1 );
    }
        
    CPerfStatLuaTiming::GetSingleton ()->UpdateLuaTiming ( pLuaMain, szFunction, GetTimeUs() - startTime );
    return true;
}
Пример #3
0
bool CLuaArguments::Call ( CLuaMain* pLuaMain, int iLuaFunction, CLuaArguments * returnValues ) const
{
    assert ( pLuaMain );

    // Add the function name to the stack and get the event from the table
    lua_State* luaVM = pLuaMain->GetVirtualMachine ();
    assert ( luaVM );
    LUA_CHECKSTACK ( luaVM, 1 );
    int luaStackPointer = lua_gettop ( luaVM );
    lua_getref ( luaVM, iLuaFunction );

    // Push our arguments onto the stack
    PushArguments ( luaVM );

    // Call the function with our arguments
    pLuaMain->ResetInstructionCount ();

    int iret = lua_pcall ( luaVM, m_Arguments.size (), LUA_MULTRET, 0 );
    if ( iret == LUA_ERRRUN || iret == LUA_ERRMEM )
    {
        const char* szRes = lua_tostring( luaVM, -1 );		
		g_pGame->GetScriptDebugging()->LogError ( luaVM, "%s", szRes );

        // cleanup the stack
        while ( lua_gettop ( luaVM ) - luaStackPointer > 0 )
            lua_pop ( luaVM, 1 );

       return false; // the function call failed
    }
    else
    {
        int iReturns = lua_gettop ( luaVM ) - luaStackPointer;

        if ( returnValues != NULL )
        {
            for ( int i = - iReturns; i <= -1; i++ )
            {
                returnValues->ReadArgument ( luaVM, i );
            }
        }

        // cleanup the stack
        while ( lua_gettop ( luaVM ) - luaStackPointer > 0 )
            lua_pop ( luaVM, 1 );
    }
        
    return true;
}
Пример #4
0
void CLuaArguments::PushAsTable(lua_State* luaVM, CFastHashMap<CLuaArguments*, int>* pKnownTables)
{
    // Ensure there is enough space on the Lua stack
    LUA_CHECKSTACK(luaVM, 4);

    bool bKnownTablesCreated = false;
    if (!pKnownTables)
    {
        pKnownTables = new CFastHashMap<CLuaArguments*, int>();
        bKnownTablesCreated = true;

        lua_newtable(luaVM);
        // using registry to make it fail safe, else we'd have to carry
        // either lua top or current depth variable between calls
        lua_setfield(luaVM, LUA_REGISTRYINDEX, "cache");
    }

    lua_newtable(luaVM);

    // push it onto the known tables
    int size = pKnownTables->size();
    lua_getfield(luaVM, LUA_REGISTRYINDEX, "cache");
    lua_pushnumber(luaVM, ++size);
    lua_pushvalue(luaVM, -3);
    lua_settable(luaVM, -3);
    lua_pop(luaVM, 1);
    pKnownTables->insert(std::make_pair((CLuaArguments*)this, size));

    vector<CLuaArgument*>::const_iterator iter = m_Arguments.begin();
    for (; iter != m_Arguments.end() && (iter + 1) != m_Arguments.end(); ++iter)
    {
        (*iter)->Push(luaVM, pKnownTables);            // index
        ++iter;
        (*iter)->Push(luaVM, pKnownTables);            // value
        lua_settable(luaVM, -3);
    }

    if (bKnownTablesCreated)
    {
        // clear the cache
        lua_pushnil(luaVM);
        lua_setfield(luaVM, LUA_REGISTRYINDEX, "cache");
        delete pKnownTables;
    }
}
Пример #5
0
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< CMapEvent* > matchingEvents;
    for ( EventsIter iter = itPair.first ; iter != itPair.second ; ++iter )
        matchingEvents.push_back(iter->second);

    for ( std::vector< CMapEvent* >::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 );

                    // 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;

                    // 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;
}
Пример #6
0
bool CLuaArguments::Call ( CLuaMain* pLuaMain, const CLuaFunctionRef& iLuaFunction, CLuaArguments * returnValues ) const
{
    assert ( pLuaMain );
    TIMEUS startTime = GetTimeUs ();

    // Add the function name to the stack and get the event from the table
    lua_State* luaVM = pLuaMain->GetVirtualMachine ();
    assert ( luaVM );
    LUA_CHECKSTACK ( luaVM, 1 );
    int luaStackPointer = lua_gettop ( luaVM );
    lua_getref ( luaVM, iLuaFunction.ToInt () );

    // Push our arguments onto the stack
    PushArguments ( luaVM );

    // Call the function with our arguments
    pLuaMain->ResetInstructionCount ();

    int iret = lua_pcall ( luaVM, m_Arguments.size (), LUA_MULTRET, 0 );
    if ( iret == LUA_ERRRUN || iret == LUA_ERRMEM )
    {
        SString strRes = ConformResourcePath ( lua_tostring( luaVM, -1 ) );
        
        vector <SString> vecSplit;
        strRes.Split ( ":", vecSplit );
        
        if ( vecSplit.size ( ) >= 3 )
        {
            SString strFile = vecSplit[0];
            int     iLine   = atoi ( vecSplit[1].c_str ( ) );
            SString strMsg  = vecSplit[2].substr ( 1 );
            
            g_pGame->GetScriptDebugging()->LogError ( strFile, iLine, strMsg );
        }
        else
            g_pGame->GetScriptDebugging()->LogError ( luaVM, "%s", strRes.c_str () );

        // cleanup the stack
        while ( lua_gettop ( luaVM ) - luaStackPointer > 0 )
            lua_pop ( luaVM, 1 );

       return false; // the function call failed
    }
    else
    {
        int iReturns = lua_gettop ( luaVM ) - luaStackPointer;

        if ( returnValues != NULL )
        {
            for ( int i = - iReturns; i <= -1; i++ )
            {
                returnValues->ReadArgument ( luaVM, i );
            }
        }

        // cleanup the stack
        while ( lua_gettop ( luaVM ) - luaStackPointer > 0 )
            lua_pop ( luaVM, 1 );
    }

    CPerfStatLuaTiming::GetSingleton ()->UpdateLuaTiming ( pLuaMain, pLuaMain->GetFunctionTag ( iLuaFunction.m_iFunction ), GetTimeUs() - startTime );
    return true;
}