mirror of
				https://github.com/VCMP-SqMod/SqMod.git
				synced 2025-11-04 00:07:19 +01:00 
			
		
		
		
	Fix the script loading process and further improve it with multi stage loading of scripts.
This commit is contained in:
		
							
								
								
									
										187
									
								
								source/Core.cpp
									
									
									
									
									
								
							
							
						
						
									
										187
									
								
								source/Core.cpp
									
									
									
									
									
								
							@@ -127,6 +127,7 @@ Core::Core()
 | 
				
			|||||||
    : m_State(0)
 | 
					    : m_State(0)
 | 
				
			||||||
    , m_VM(nullptr)
 | 
					    , m_VM(nullptr)
 | 
				
			||||||
    , m_Scripts()
 | 
					    , m_Scripts()
 | 
				
			||||||
 | 
					    , m_PendingScripts()
 | 
				
			||||||
    , m_Options()
 | 
					    , m_Options()
 | 
				
			||||||
    , m_Blips()
 | 
					    , m_Blips()
 | 
				
			||||||
    , m_Checkpoints()
 | 
					    , m_Checkpoints()
 | 
				
			||||||
@@ -300,7 +301,7 @@ bool Core::Initialize()
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // See if any script could be queued for loading
 | 
					    // See if any script could be queued for loading
 | 
				
			||||||
    if (m_Scripts.empty() && !conf.GetBoolValue("Squirrel", "EmptyInit", false))
 | 
					    if (m_PendingScripts.empty() && !conf.GetBoolValue("Squirrel", "EmptyInit", false))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        LogErr("No scripts loaded. No reason to load the plug-in");
 | 
					        LogErr("No scripts loaded. No reason to load the plug-in");
 | 
				
			||||||
        // No point in loading the plug-in
 | 
					        // No point in loading the plug-in
 | 
				
			||||||
@@ -344,7 +345,7 @@ bool Core::Initialize()
 | 
				
			|||||||
bool Core::Execute()
 | 
					bool Core::Execute()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // Are there any scripts to execute?
 | 
					    // Are there any scripts to execute?
 | 
				
			||||||
    if (cLogErr(m_Scripts.empty(), "No scripts to execute. Plug-in has no purpose"))
 | 
					    if (cLogErr(m_PendingScripts.empty(), "No scripts to execute. Plug-in has no purpose"))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return false; // No reason to execute the plug-in
 | 
					        return false; // No reason to execute the plug-in
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -353,74 +354,21 @@ bool Core::Execute()
 | 
				
			|||||||
    // Tell modules to do their monkey business
 | 
					    // Tell modules to do their monkey business
 | 
				
			||||||
    _Func->SendPluginCommand(SQMOD_LOAD_CMD, "");
 | 
					    _Func->SendPluginCommand(SQMOD_LOAD_CMD, "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    LogDbg("Attempting to compile the specified scripts");
 | 
					    // Load pending scripts while we're in the bounds of the allowed recursiveness
 | 
				
			||||||
    // Compile scripts first so that the constants can take effect
 | 
					    for (unsigned levels = 0; (m_PendingScripts.empty() == false) && (levels < 8); ++levels)
 | 
				
			||||||
    for (auto & s : m_Scripts)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Is this script already compiled?
 | 
					        // Remember the last script from the pool
 | 
				
			||||||
        if (!s.mExec.IsNull())
 | 
					        const Scripts::size_type last = m_Scripts.size();
 | 
				
			||||||
 | 
					        // Push pending scripts to the back of the list
 | 
				
			||||||
 | 
					        std::move(m_PendingScripts.begin(), m_PendingScripts.end(), std::back_inserter(m_Scripts));
 | 
				
			||||||
 | 
					        // Clear all pending scripts, if any
 | 
				
			||||||
 | 
					        m_PendingScripts.clear();
 | 
				
			||||||
 | 
					        // Process all pending scripts
 | 
				
			||||||
 | 
					        if (DoScripts(m_Scripts.begin() + last, m_Scripts.end()) == false)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            continue; // Already compiled!
 | 
					            return false; // One of the scripts failed to execute
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        LogDbg("Completed execution of stage (%u) scripts", levels);
 | 
				
			||||||
        // Attempt to load and compile the script file
 | 
					 | 
				
			||||||
        try
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            s.mExec.CompileFile(s.mPath);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        catch (const Sqrat::Exception & e)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            LogFtl("Unable to compile: %s", s.mPath.c_str());
 | 
					 | 
				
			||||||
            // Failed to execute properly
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        LogDbg("Successfully compiled script: %s", s.mPath.c_str());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Should we delay the execution of this script?
 | 
					 | 
				
			||||||
        if (s.mDelay)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            continue; // Execute later!
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Attempt to execute the compiled script code
 | 
					 | 
				
			||||||
        try
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            s.mExec.Run();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        catch (const Sqrat::Exception & e)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            LogFtl("Unable to execute: %s", s.mPath.c_str());
 | 
					 | 
				
			||||||
            // Failed to execute properly
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        LogScs("Successfully executed script: %s", s.mPath.c_str());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    LogDbg("Attempting to execute the specified scripts");
 | 
					 | 
				
			||||||
    // Execute scripts only after compilation successful
 | 
					 | 
				
			||||||
    for (auto & s : m_Scripts)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // Was this script delayed from execution?
 | 
					 | 
				
			||||||
        if (!s.mDelay)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            continue; // Already executed!
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Attempt to execute the compiled script code
 | 
					 | 
				
			||||||
        try
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            s.mExec.Run();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        catch (const Sqrat::Exception & e)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            LogFtl("Unable to execute: %s", s.mPath.c_str());
 | 
					 | 
				
			||||||
            // Failed to execute properly
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        LogScs("Successfully executed script: %s", s.mPath.c_str());
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create the null entity instances
 | 
					    // Create the null entity instances
 | 
				
			||||||
@@ -496,6 +444,7 @@ void Core::Terminate(bool shutdown)
 | 
				
			|||||||
        ResetFunc();
 | 
					        ResetFunc();
 | 
				
			||||||
        // Release the script instances
 | 
					        // Release the script instances
 | 
				
			||||||
        m_Scripts.clear();
 | 
					        m_Scripts.clear();
 | 
				
			||||||
 | 
					        m_PendingScripts.clear(); // Just in case
 | 
				
			||||||
        // Specify that no scripts are left executed
 | 
					        // Specify that no scripts are left executed
 | 
				
			||||||
        m_Executed = false;
 | 
					        m_Executed = false;
 | 
				
			||||||
        // Assertions during close may cause double delete/close!
 | 
					        // Assertions during close may cause double delete/close!
 | 
				
			||||||
@@ -509,7 +458,7 @@ void Core::Terminate(bool shutdown)
 | 
				
			|||||||
        _Func->SendPluginCommand(SQMOD_RELEASED_CMD, "");
 | 
					        _Func->SendPluginCommand(SQMOD_RELEASED_CMD, "");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    LogDbg("Squirrel plugin was successfully terminated");
 | 
					    LogDbg("Squirrel plug---in was successfully terminated");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ------------------------------------------------------------------------------------------------
 | 
					// ------------------------------------------------------------------------------------------------
 | 
				
			||||||
@@ -569,6 +518,7 @@ bool Core::LoadScript(CSStr filepath, bool delay)
 | 
				
			|||||||
        // Failed to load
 | 
					        // Failed to load
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Buffer bpath;
 | 
					    Buffer bpath;
 | 
				
			||||||
    // Attempt to get the real file path
 | 
					    // Attempt to get the real file path
 | 
				
			||||||
    try
 | 
					    try
 | 
				
			||||||
@@ -587,8 +537,10 @@ bool Core::LoadScript(CSStr filepath, bool delay)
 | 
				
			|||||||
        // Failed to load
 | 
					        // Failed to load
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Make the path into a string
 | 
					    // Make the path into a string
 | 
				
			||||||
    String path(bpath.Data(), bpath.Position());
 | 
					    String path(bpath.Data(), bpath.Position());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // See if it wasn't already loaded
 | 
					    // See if it wasn't already loaded
 | 
				
			||||||
    if (std::find_if(m_Scripts.cbegin(), m_Scripts.cend(), [&path](Scripts::const_reference s) {
 | 
					    if (std::find_if(m_Scripts.cbegin(), m_Scripts.cend(), [&path](Scripts::const_reference s) {
 | 
				
			||||||
        return (s.mPath == path);
 | 
					        return (s.mPath == path);
 | 
				
			||||||
@@ -596,6 +548,13 @@ bool Core::LoadScript(CSStr filepath, bool delay)
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        LogWrn("Script was specified before: %s", path.c_str());
 | 
					        LogWrn("Script was specified before: %s", path.c_str());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    // Also check the pending scripts container
 | 
				
			||||||
 | 
					    else if (std::find_if(m_PendingScripts.cbegin(), m_PendingScripts.cend(), [&path](Scripts::const_reference s) {
 | 
				
			||||||
 | 
					        return (s.mPath == path);
 | 
				
			||||||
 | 
					    }) != m_PendingScripts.end())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        LogWrn("Script was specified before: %s", path.c_str());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    // Were the scripts already executed? Then there's no need to queue them
 | 
					    // Were the scripts already executed? Then there's no need to queue them
 | 
				
			||||||
    else if (m_Executed)
 | 
					    else if (m_Executed)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -610,7 +569,9 @@ bool Core::LoadScript(CSStr filepath, bool delay)
 | 
				
			|||||||
        catch (const Sqrat::Exception & e)
 | 
					        catch (const Sqrat::Exception & e)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            LogFtl("Unable to compile: %s", m_Scripts.back().mPath.c_str());
 | 
					            LogFtl("Unable to compile: %s", m_Scripts.back().mPath.c_str());
 | 
				
			||||||
            // Failed to execute properly
 | 
					            // Remove the script container since it's invalid
 | 
				
			||||||
 | 
					            m_Scripts.pop_back();
 | 
				
			||||||
 | 
					            // Failed to compile properly
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // At this point the script should be completely loaded
 | 
					        // At this point the script should be completely loaded
 | 
				
			||||||
@@ -624,6 +585,8 @@ bool Core::LoadScript(CSStr filepath, bool delay)
 | 
				
			|||||||
        catch (const Sqrat::Exception & e)
 | 
					        catch (const Sqrat::Exception & e)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            LogFtl("Unable to execute: %s", m_Scripts.back().mPath.c_str());
 | 
					            LogFtl("Unable to execute: %s", m_Scripts.back().mPath.c_str());
 | 
				
			||||||
 | 
					            // Remove the script container since it's invalid
 | 
				
			||||||
 | 
					            m_Scripts.pop_back();
 | 
				
			||||||
            // Failed to execute properly
 | 
					            // Failed to execute properly
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -633,10 +596,11 @@ bool Core::LoadScript(CSStr filepath, bool delay)
 | 
				
			|||||||
    // We don't compile the scripts yet. We just store their path and prepare the objects
 | 
					    // We don't compile the scripts yet. We just store their path and prepare the objects
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Create a new script container and insert it into the script pool
 | 
					        // Create a new script container and insert it into the pending script pool
 | 
				
			||||||
        m_Scripts.emplace_back(m_VM, std::move(path), delay, m_Debugging);
 | 
					        m_PendingScripts.emplace_back(m_VM, std::move(path), delay, m_Debugging);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // At this point the script exists in the pool
 | 
					
 | 
				
			||||||
 | 
					    // At this point the script exists in one of the pools
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -671,6 +635,85 @@ void Core::SetIncomingName(CSStr name)
 | 
				
			|||||||
    m_IncomingNameBuffer[len] = '\0';
 | 
					    m_IncomingNameBuffer[len] = '\0';
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ------------------------------------------------------------------------------------------------
 | 
				
			||||||
 | 
					bool Core::DoScripts(Scripts::iterator itr, Scripts::iterator end)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Scripts::iterator itr_state = itr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LogDbg("Attempting to compile the specified scripts");
 | 
				
			||||||
 | 
					    // Compile scripts first so that the constants can take effect
 | 
				
			||||||
 | 
					    for (; itr != end; ++itr)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Is this script already compiled?
 | 
				
			||||||
 | 
					        if (!(*itr).mExec.IsNull())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            continue; // Already compiled!
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Attempt to load and compile the script file
 | 
				
			||||||
 | 
					        try
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            (*itr).mExec.CompileFile((*itr).mPath);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        catch (const Sqrat::Exception & e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            LogFtl("Unable to compile: %s", (*itr).mPath.c_str());
 | 
				
			||||||
 | 
					            // Failed to execute properly
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        LogDbg("Successfully compiled script: %s", (*itr).mPath.c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Should we delay the execution of this script?
 | 
				
			||||||
 | 
					        if ((*itr).mDelay)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            continue; // Execute later!
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Attempt to execute the compiled script code
 | 
				
			||||||
 | 
					        try
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            (*itr).mExec.Run();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        catch (const Sqrat::Exception & e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            LogFtl("Unable to execute: %s", (*itr).mPath.c_str());
 | 
				
			||||||
 | 
					            // Failed to execute properly
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        LogScs("Successfully executed script: %s", (*itr).mPath.c_str());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LogDbg("Attempting to execute the specified scripts");
 | 
				
			||||||
 | 
					    // Execute scripts only after compilation successful
 | 
				
			||||||
 | 
					    for (itr = itr_state; itr != end; ++itr)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Was this script delayed from execution?
 | 
				
			||||||
 | 
					        if (!(*itr).mDelay)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            continue; // Already executed!
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Attempt to execute the compiled script code
 | 
				
			||||||
 | 
					        try
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            (*itr).mExec.Run();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        catch (const Sqrat::Exception & e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            LogFtl("Unable to execute: %s", (*itr).mPath.c_str());
 | 
				
			||||||
 | 
					            // Failed to execute properly
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        LogScs("Successfully executed script: %s", (*itr).mPath.c_str());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // At this point the scripts were loaded and executed successfully
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ------------------------------------------------------------------------------------------------
 | 
					// ------------------------------------------------------------------------------------------------
 | 
				
			||||||
void Core::PrintFunc(HSQUIRRELVM /*vm*/, CSStr msg, ...)
 | 
					void Core::PrintFunc(HSQUIRRELVM /*vm*/, CSStr msg, ...)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -536,6 +536,7 @@ private:
 | 
				
			|||||||
    Int32                           m_State; // Current plug-in state.
 | 
					    Int32                           m_State; // Current plug-in state.
 | 
				
			||||||
    HSQUIRRELVM                     m_VM; // Script virtual machine.
 | 
					    HSQUIRRELVM                     m_VM; // Script virtual machine.
 | 
				
			||||||
    Scripts                         m_Scripts; // Loaded scripts objects.
 | 
					    Scripts                         m_Scripts; // Loaded scripts objects.
 | 
				
			||||||
 | 
					    Scripts                         m_PendingScripts; // Pending scripts objects.
 | 
				
			||||||
    Options                         m_Options; // Custom configuration options.
 | 
					    Options                         m_Options; // Custom configuration options.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // --------------------------------------------------------------------------------------------
 | 
					    // --------------------------------------------------------------------------------------------
 | 
				
			||||||
@@ -735,6 +736,11 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* --------------------------------------------------------------------------------------------
 | 
				
			||||||
 | 
					     * Script execution process.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    static bool DoScripts(Scripts::iterator itr, Scripts::iterator end);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* --------------------------------------------------------------------------------------------
 | 
					    /* --------------------------------------------------------------------------------------------
 | 
				
			||||||
     * Script output handlers.
 | 
					     * Script output handlers.
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user