Skip to content

Commit e72201e

Browse files
committed
Whole buncha fixes for mod compatibility:
* Activities are in the global state again * Activity functions are continually refreshed to account for dofiles * loadfile now accounts for Data/Mods directory
1 parent cbf6c5b commit e72201e

File tree

6 files changed

+91
-49
lines changed

6 files changed

+91
-49
lines changed

Activities/GAScripted.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -204,17 +204,30 @@ int GAScripted::ReloadScripts() {
204204
}
205205
}
206206

207-
std::unordered_map<std::string, LuabindObjectWrapper*> scriptFileFunctions;
208-
if ((error = g_LuaMan.GetMasterScriptState().RunScriptFileAndRetrieveFunctions(m_ScriptPath, m_LuaClassName, GetSupportedScriptFunctionNames(), scriptFileFunctions, true)) < 0) {
207+
if ((error = g_LuaMan.GetMasterScriptState().RunScriptFile(m_ScriptPath, true, false)) < 0) {
209208
return error;
210209
}
211210

211+
RefreshActivityFunctions();
212+
213+
return 0;
214+
}
215+
216+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
217+
218+
void GAScripted::RefreshActivityFunctions() {
212219
m_ScriptFunctions.clear();
220+
if (m_ScriptPath.empty()) {
221+
return;
222+
}
223+
224+
// We use m_LuaClassName here, because we ran the script file in the global state instead of in an environment
225+
std::unordered_map<std::string, LuabindObjectWrapper*> scriptFileFunctions;
226+
g_LuaMan.GetMasterScriptState().RetrieveFunctions(m_LuaClassName, GetSupportedScriptFunctionNames(), scriptFileFunctions);
227+
213228
for (const auto& [functionName, functionObject] : scriptFileFunctions) {
214229
m_ScriptFunctions[functionName] = std::unique_ptr<LuabindObjectWrapper>(functionObject);
215230
}
216-
217-
return 0;
218231
}
219232

220233
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -485,7 +498,12 @@ int GAScripted::RunLuaFunction(const std::string& functionName, const std::vecto
485498
return 0;
486499
}
487500

488-
return g_LuaMan.GetMasterScriptState().RunScriptFunctionObject(funcItr->second.get(), "_G", m_LuaClassName, functionEntityArguments, functionLiteralArguments, functionObjectArguments);
501+
int error = g_LuaMan.GetMasterScriptState().RunScriptFunctionObject(funcItr->second.get(), "_G", m_LuaClassName, functionEntityArguments, functionLiteralArguments, functionObjectArguments);
502+
503+
// Need to call this continually unfortunately, as something might change due to dofile()
504+
RefreshActivityFunctions();
505+
506+
return error;
489507
}
490508

491509

Activities/GAScripted.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ ClassInfoGetters;
139139

140140
int ReloadScripts() override;
141141

142+
/// <summary>
143+
/// Refreshes our activity functions to find any changes from script.
144+
/// </summary>
145+
void RefreshActivityFunctions();
146+
142147

143148
//////////////////////////////////////////////////////////////////////////////////////////
144149
// Virtual method: GetLuaClassName

Entities/MovableObject.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ int MovableObject::LoadScript(const std::string &scriptPath, bool loadAsEnabledS
587587
m_AllLoadedScripts.try_emplace(scriptPath, loadAsEnabledScript);
588588

589589
std::unordered_map<std::string, LuabindObjectWrapper *> scriptFileFunctions;
590-
if (usedState.RunScriptFileAndRetrieveFunctions(scriptPath, "", GetSupportedScriptFunctionNames(), scriptFileFunctions) < 0) {
590+
if (usedState.RunScriptFileAndRetrieveFunctions(scriptPath, GetSupportedScriptFunctionNames(), scriptFileFunctions) < 0) {
591591
return -4;
592592
}
593593

Entities/PieSlice.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ namespace RTE {
170170
std::string filePath = m_LuabindFunctionObject->GetFilePath();
171171
std::unordered_map<std::string, LuabindObjectWrapper *> scriptFileFunctions;
172172

173-
status = g_LuaMan.GetMasterScriptState().RunScriptFileAndRetrieveFunctions(filePath, "", { m_FunctionName }, scriptFileFunctions, true);
173+
status = g_LuaMan.GetMasterScriptState().RunScriptFileAndRetrieveFunctions(filePath, { m_FunctionName }, scriptFileFunctions, true);
174174
if (scriptFileFunctions.find(m_FunctionName) != scriptFileFunctions.end()) {
175175
m_LuabindFunctionObject = std::unique_ptr<LuabindObjectWrapper>(scriptFileFunctions.at(m_FunctionName));
176176
}

Managers/LuaMan.cpp

Lines changed: 49 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
namespace RTE {
1111

12-
const std::unordered_set<std::string> LuaMan::c_FileAccessModes = { "r", "r+", "w", "w+", "a", "a+" };
12+
const std::unordered_set<std::string> LuaMan::c_FileAccessModes = { "r", "r+", "w", "w+", "a", "a+", "rt", "wt"};
1313

1414
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1515

@@ -227,8 +227,9 @@ namespace RTE {
227227
// Override "math.random" in the lua state to use RTETools MT19937 implementation. Preserve return types of original to not break all the things.
228228
"math.random = function(lower, upper) if lower ~= nil and upper ~= nil then return LuaMan:SelectRand(lower, upper); elseif lower ~= nil then return LuaMan:SelectRand(1, lower); else return LuaMan:PosRand(); end end"
229229
"\n"
230-
// Override "dofile" to be able to account for Data/ or Mods/ directory.
230+
// Override "dofile"/"loadfile" to be able to account for Data/ or Mods/ directory.
231231
"OriginalDoFile = dofile; dofile = function(filePath) filePath = PresetMan:GetFullModulePath(filePath); if filePath ~= '' then return OriginalDoFile(filePath); end end;"
232+
"OriginalLoadFile = loadfile; loadfile = function(filePath) filePath = PresetMan:GetFullModulePath(filePath); if filePath ~= '' then return OriginalLoadFile(filePath); end end;"
232233
// Internal helper functions to add callbacks for async pathing requests
233234
"_AsyncPathCallbacks = {};"
234235
"_AddAsyncPathCallback = function(id, callback) _AsyncPathCallbacks[id] = callback; end\n"
@@ -636,7 +637,7 @@ namespace RTE {
636637

637638
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
638639

639-
int LuaStateWrapper::RunScriptFile(const std::string &filePath, bool consoleErrors) {
640+
int LuaStateWrapper::RunScriptFile(const std::string &filePath, bool consoleErrors, bool doInSandboxedEnvironment) {
640641
const std::string fullScriptPath = g_PresetMan.GetFullModulePath(filePath);
641642
if (fullScriptPath.empty()) {
642643
m_LastError = "Can't run a script file with an empty filepath!";
@@ -674,20 +675,22 @@ namespace RTE {
674675
}
675676

676677
if (error == 0) {
677-
// create a new environment table
678-
lua_getglobal(m_State, filePath.c_str());
679-
if (lua_isnil(m_State, -1)) {
680-
lua_pop(m_State, 1);
681-
lua_newtable(m_State);
682-
lua_newtable(m_State);
683-
lua_getglobal(m_State, "_G");
684-
lua_setfield(m_State, -2, "__index");
685-
lua_setmetatable(m_State, -2);
686-
lua_setglobal(m_State, filePath.c_str());
678+
if (doInSandboxedEnvironment) {
679+
// create a new environment table
687680
lua_getglobal(m_State, filePath.c_str());
688-
}
681+
if (lua_isnil(m_State, -1)) {
682+
lua_pop(m_State, 1);
683+
lua_newtable(m_State);
684+
lua_newtable(m_State);
685+
lua_getglobal(m_State, "_G");
686+
lua_setfield(m_State, -2, "__index");
687+
lua_setmetatable(m_State, -2);
688+
lua_setglobal(m_State, filePath.c_str());
689+
lua_getglobal(m_State, filePath.c_str());
690+
}
689691

690-
lua_setfenv(m_State, -2);
692+
lua_setfenv(m_State, -2);
693+
}
691694

692695
// execute script file with pcall. Pcall will call the file and line error handler if there's an error by pointing 2 up the stack to it.
693696
if (lua_pcall(m_State, 0, LUA_MULTRET, -2)) {
@@ -710,7 +713,36 @@ namespace RTE {
710713

711714
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
712715

713-
int LuaStateWrapper::RunScriptFileAndRetrieveFunctions(const std::string &filePath, const std::string &prefix, const std::vector<std::string> &functionNamesToLookFor, std::unordered_map<std::string, LuabindObjectWrapper *> &outFunctionNamesAndObjects, bool forceReload) {
716+
bool LuaStateWrapper::RetrieveFunctions(const std::string& funcObjectName, const std::vector<std::string>& functionNamesToLookFor, std::unordered_map<std::string, LuabindObjectWrapper*>& outFunctionNamesAndObjects) {
717+
std::lock_guard<std::recursive_mutex> lock(m_Mutex);
718+
s_currentLuaState = this;
719+
720+
luabind::object funcHoldingObject = luabind::globals(m_State)[funcObjectName.c_str()];
721+
if (luabind::type(funcHoldingObject) == LUA_TNIL) {
722+
return false;
723+
}
724+
725+
auto& newScript = m_ScriptCache[funcObjectName.c_str()];
726+
newScript.functionNamesAndObjects.clear();
727+
for (const std::string& functionName : functionNamesToLookFor) {
728+
luabind::object functionObject = funcHoldingObject[functionName];
729+
if (luabind::type(functionObject) == LUA_TFUNCTION) {
730+
luabind::object* functionObjectCopyForStoring = new luabind::object(functionObject);
731+
newScript.functionNamesAndObjects.try_emplace(functionName, new LuabindObjectWrapper(functionObjectCopyForStoring, funcObjectName));
732+
}
733+
}
734+
735+
for (auto& pair : newScript.functionNamesAndObjects) {
736+
luabind::object* functionObjectCopyForStoring = new luabind::object(*pair.second->GetLuabindObject());
737+
outFunctionNamesAndObjects.try_emplace(pair.first, new LuabindObjectWrapper(functionObjectCopyForStoring, funcObjectName));
738+
}
739+
740+
return true;
741+
}
742+
743+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
744+
745+
int LuaStateWrapper::RunScriptFileAndRetrieveFunctions(const std::string &filePath, const std::vector<std::string> &functionNamesToLookFor, std::unordered_map<std::string, LuabindObjectWrapper *> &outFunctionNamesAndObjects, bool forceReload) {
714746
static bool disableCaching = false;
715747
forceReload = forceReload || disableCaching;
716748

@@ -733,32 +765,10 @@ namespace RTE {
733765
return error;
734766
}
735767

736-
luabind::object prefixObject;
737-
if (prefix == "") {
738-
prefixObject = luabind::globals(m_State)[filePath.c_str()];
739-
} else {
740-
prefixObject = luabind::globals(m_State)[filePath.c_str()][prefix];
741-
}
742-
743-
if (luabind::type(prefixObject) == LUA_TNIL) {
768+
if (!RetrieveFunctions(filePath, functionNamesToLookFor, outFunctionNamesAndObjects)) {
744769
return -1;
745770
}
746771

747-
auto &newScript = m_ScriptCache[filePath];
748-
newScript.functionNamesAndObjects.clear();
749-
for (const std::string& functionName : functionNamesToLookFor) {
750-
luabind::object functionObject = prefixObject[functionName];
751-
if (luabind::type(functionObject) == LUA_TFUNCTION) {
752-
luabind::object* functionObjectCopyForStoring = new luabind::object(functionObject);
753-
newScript.functionNamesAndObjects.try_emplace(functionName, new LuabindObjectWrapper(functionObjectCopyForStoring, filePath));
754-
}
755-
}
756-
757-
for (auto& pair : newScript.functionNamesAndObjects) {
758-
luabind::object* functionObjectCopyForStoring = new luabind::object(*pair.second->GetLuabindObject());
759-
outFunctionNamesAndObjects.try_emplace(pair.first, new LuabindObjectWrapper(functionObjectCopyForStoring, filePath));
760-
}
761-
762772
return 0;
763773
}
764774

Managers/LuaMan.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,19 +148,28 @@ namespace RTE {
148148
/// </summary>
149149
/// <param name="filePath">The path to the file to load and run.</param>
150150
/// <param name="consoleErrors">Whether to report any errors to the console immediately.</param>
151+
/// <param name="doInSandboxedEnvironment">Whether to do it in a sandboxed environment, or the global environment.</param>
151152
/// <returns>Returns less than zero if any errors encountered when running this script. To get the actual error string, call GetLastError.</returns>
152-
int RunScriptFile(const std::string &filePath, bool consoleErrors = true);
153+
int RunScriptFile(const std::string &filePath, bool consoleErrors = true, bool doInSandboxedEnvironment = true);
154+
155+
/// <summary>
156+
/// Retrieves all of the specified functions that exist into the output map, and refreshes the cache.
157+
/// </summary>
158+
/// <param name="filePath">The path to the file to load and run.</param>
159+
/// <param name="functionNamesToLookFor">The vector of strings defining the function names to be retrieved.</param>
160+
/// <param name="outFunctionNamesAndObjects">The map of function names to LuabindObjectWrappers to be retrieved from the script that was run.</param>
161+
/// <returns>Returns whether functions were successfully retrieved.</returns>
162+
bool RetrieveFunctions(const std::string& functionObjectName, const std::vector<std::string>& functionNamesToLookFor, std::unordered_map<std::string, LuabindObjectWrapper*>& outFunctionNamesAndObjects);
153163

154164
/// <summary>
155165
/// Opens and loads a file containing a script and runs it on the state, then retrieves all of the specified functions that exist into the output map.
156166
/// </summary>
157167
/// <param name="filePath">The path to the file to load and run.</param>
158-
/// <param name="prefix">The prefix before each function we're looking for. With normal objects this is usually nothing (free floating), but activities expect the activity name beforehand.</param>
159168
/// <param name="functionNamesToLookFor">The vector of strings defining the function names to be retrieved.</param>
160169
/// <param name="outFunctionNamesAndObjects">The map of function names to LuabindObjectWrappers to be retrieved from the script that was run.</param>
161170
/// <param name="noCaching">Whether caching shouldn't be used.</param>
162171
/// <returns>Returns less than zero if any errors encountered when running this script. To get the actual error string, call GetLastError.</returns>
163-
int RunScriptFileAndRetrieveFunctions(const std::string &filePath, const std::string &prefix, const std::vector<std::string> &functionNamesToLookFor, std::unordered_map<std::string, LuabindObjectWrapper *> &outFunctionNamesAndObjects, bool forceReload = false);
172+
int RunScriptFileAndRetrieveFunctions(const std::string &filePath, const std::vector<std::string> &functionNamesToLookFor, std::unordered_map<std::string, LuabindObjectWrapper *> &outFunctionNamesAndObjects, bool forceReload = false);
164173
#pragma endregion
165174

166175
#pragma region Concrete Methods

0 commit comments

Comments
 (0)