@@ -71,8 +71,17 @@ namespace RTE {
71
71
.def (" GetDirectoryList" , &LuaStateWrapper::DirectoryList, luabind::adopt (luabind::return_value) + luabind::return_stl_iterator)
72
72
.def (" GetFileList" , &LuaStateWrapper::FileList, luabind::adopt (luabind::return_value) + luabind::return_stl_iterator)
73
73
.def (" FileExists" , &LuaStateWrapper::FileExists)
74
+ .def (" DirectoryExists" , &LuaStateWrapper::DirectoryExists)
75
+ .def (" IsValidModulePath" , &LuaStateWrapper::IsValidModulePath)
74
76
.def (" FileOpen" , &LuaStateWrapper::FileOpen)
75
77
.def (" FileClose" , &LuaStateWrapper::FileClose)
78
+ .def (" FileRemove" , &LuaStateWrapper::FileRemove)
79
+ .def (" DirectoryCreate" , &LuaStateWrapper::DirectoryCreate1)
80
+ .def (" DirectoryCreate" , &LuaStateWrapper::DirectoryCreate2)
81
+ .def (" DirectoryRemove" , &LuaStateWrapper::DirectoryRemove1)
82
+ .def (" DirectoryRemove" , &LuaStateWrapper::DirectoryRemove2)
83
+ .def (" FileRename" , &LuaStateWrapper::FileRename)
84
+ .def (" DirectoryRename" , &LuaStateWrapper::DirectoryRename)
76
85
.def (" FileReadLine" , &LuaStateWrapper::FileReadLine)
77
86
.def (" FileWriteLine" , &LuaStateWrapper::FileWriteLine)
78
87
.def (" FileEOF" , &LuaStateWrapper::FileEOF),
@@ -273,12 +282,21 @@ namespace RTE {
273
282
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
274
283
275
284
// Passthrough LuaMan Functions
276
- const std::vector<std::string>* LuaStateWrapper::DirectoryList (const std::string& relativeDirectory) { return g_LuaMan.DirectoryList (relativeDirectory); }
277
- const std::vector<std::string>* LuaStateWrapper::FileList (const std::string& relativeDirectory) { return g_LuaMan.FileList (relativeDirectory); }
278
- bool LuaStateWrapper::FileExists (const std::string &fileName) { return g_LuaMan.FileExists (fileName); }
279
- int LuaStateWrapper::FileOpen (const std::string& fileName, const std::string& accessMode) { return g_LuaMan.FileOpen (fileName, accessMode); }
285
+ const std::vector<std::string>* LuaStateWrapper::DirectoryList (const std::string& path) { return g_LuaMan.DirectoryList (path); }
286
+ const std::vector<std::string>* LuaStateWrapper::FileList (const std::string& path) { return g_LuaMan.FileList (path); }
287
+ bool LuaStateWrapper::FileExists (const std::string &path) { return g_LuaMan.FileExists (path); }
288
+ bool LuaStateWrapper::DirectoryExists (const std::string &path) { return g_LuaMan.DirectoryExists (path); }
289
+ bool LuaStateWrapper::IsValidModulePath (const std::string &path) { return g_LuaMan.IsValidModulePath (path); }
290
+ int LuaStateWrapper::FileOpen (const std::string& path, const std::string& accessMode) { return g_LuaMan.FileOpen (path, accessMode); }
280
291
void LuaStateWrapper::FileClose (int fileIndex) { return g_LuaMan.FileClose (fileIndex); }
281
292
void LuaStateWrapper::FileCloseAll () { return g_LuaMan.FileCloseAll (); }
293
+ bool LuaStateWrapper::FileRemove (const std::string& path) { return g_LuaMan.FileRemove (path); }
294
+ bool LuaStateWrapper::DirectoryCreate1 (const std::string& path) { return g_LuaMan.DirectoryCreate (path, false ); }
295
+ bool LuaStateWrapper::DirectoryCreate2 (const std::string& path, bool recursive) { return g_LuaMan.DirectoryCreate (path, recursive); }
296
+ bool LuaStateWrapper::DirectoryRemove1 (const std::string& path) { return g_LuaMan.DirectoryRemove (path, false ); }
297
+ bool LuaStateWrapper::DirectoryRemove2 (const std::string& path, bool recursive) { return g_LuaMan.DirectoryRemove (path, recursive); }
298
+ bool LuaStateWrapper::FileRename (const std::string& oldPath, const std::string& newPath) { return g_LuaMan.FileRename (oldPath, newPath); }
299
+ bool LuaStateWrapper::DirectoryRename (const std::string& oldPath, const std::string& newPath) { return g_LuaMan.DirectoryRename (oldPath, newPath); }
282
300
std::string LuaStateWrapper::FileReadLine (int fileIndex) { return g_LuaMan.FileReadLine (fileIndex); }
283
301
void LuaStateWrapper::FileWriteLine (int fileIndex, const std::string& line) { return g_LuaMan.FileWriteLine (fileIndex, line); }
284
302
bool LuaStateWrapper::FileEOF (int fileIndex) { return g_LuaMan.FileEOF (fileIndex); }
@@ -349,7 +367,7 @@ namespace RTE {
349
367
350
368
// TODO
351
369
// It would be nice to assign to least-saturated state, but that's a bit tricky with MO registering...
352
- /* auto itr = std::min_element(m_ScriptStates.begin(), m_ScriptStates.end(),
370
+ /* auto itr = std::min_element(m_ScriptStates.begin(), m_ScriptStates.end(),
353
371
[](const LuaStateWrapper& lhs, const LuaStateWrapper& rhs) { return lhs.GetRegisteredMOs().size() < rhs.GetRegisteredMOs().size(); }
354
372
);
355
373
@@ -364,7 +382,7 @@ namespace RTE {
364
382
bool success = m_ScriptStates[ourState].GetMutex ().try_lock ();
365
383
RTEAssert (success, " Script mutex was already locked while in a non-multithreaded environment!" );
366
384
367
- return &m_ScriptStates[ourState];
385
+ return &m_ScriptStates[ourState];
368
386
}
369
387
370
388
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -394,13 +412,13 @@ namespace RTE {
394
412
395
413
void LuaMan::ExecuteLuaScriptCallbacks () {
396
414
std::vector<std::function<void ()>> callbacks;
397
-
415
+
398
416
// Move our functions into the local buffer to clear the existing callbacks and to lock for as little time as possible
399
417
{
400
418
std::scoped_lock lock (m_ScriptCallbacksMutex);
401
419
callbacks.swap (m_ScriptCallbacks);
402
420
}
403
-
421
+
404
422
for (const std::function<void ()> &callback : callbacks) {
405
423
callback ();
406
424
}
@@ -860,7 +878,7 @@ namespace RTE {
860
878
861
879
bool LuaStateWrapper::TableEntryIsDefined (const std::string &tableName, const std::string &indexName) {
862
880
std::lock_guard<std::recursive_mutex> lock (m_Mutex);
863
-
881
+
864
882
// Push the table onto the stack, checking if it even exists.
865
883
lua_getglobal (m_State, tableName.c_str ());
866
884
if (!lua_istable (m_State, -1 )) {
@@ -928,40 +946,80 @@ namespace RTE {
928
946
929
947
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
930
948
931
- const std::vector<std::string> * LuaMan::DirectoryList (const std::string &filePath) {
949
+ const std::vector<std::string> * LuaMan::DirectoryList (const std::string &path) {
950
+ std::string fullPath = System::GetWorkingDirectory () + g_PresetMan.GetFullModulePath (path);
932
951
auto *directoryPaths = new std::vector<std::string>();
933
952
934
- for (const std::filesystem::directory_entry &directoryEntry : std::filesystem::directory_iterator (System::GetWorkingDirectory () + filePath)) {
935
- if (directoryEntry.is_directory ()) { directoryPaths->emplace_back (directoryEntry.path ().filename ().generic_string ()); }
953
+ if (IsValidModulePath (fullPath)) {
954
+ #ifndef _WIN32
955
+ fullPath = GetCaseInsensitiveFullPath (fullPath);
956
+ #endif
957
+ if (std::filesystem::exists (fullPath))
958
+ {
959
+ for (const std::filesystem::directory_entry &directoryEntry : std::filesystem::directory_iterator (fullPath)) {
960
+ if (directoryEntry.is_directory ()) { directoryPaths->emplace_back (directoryEntry.path ().filename ().generic_string ()); }
961
+ }
962
+ }
936
963
}
937
964
return directoryPaths;
938
965
}
939
966
940
967
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
941
968
942
- const std::vector<std::string> * LuaMan::FileList (const std::string &filePath) {
969
+ const std::vector<std::string> * LuaMan::FileList (const std::string &path) {
970
+ std::string fullPath = System::GetWorkingDirectory () + g_PresetMan.GetFullModulePath (path);
943
971
auto *filePaths = new std::vector<std::string>();
944
972
945
- for (const std::filesystem::directory_entry &directoryEntry : std::filesystem::directory_iterator (System::GetWorkingDirectory () + filePath)) {
946
- if (directoryEntry.is_regular_file ()) { filePaths->emplace_back (directoryEntry.path ().filename ().generic_string ()); }
973
+ if (IsValidModulePath (fullPath)) {
974
+ #ifndef _WIN32
975
+ fullPath = GetCaseInsensitiveFullPath (fullPath);
976
+ #endif
977
+ if (std::filesystem::exists (fullPath))
978
+ {
979
+ for (const std::filesystem::directory_entry &directoryEntry : std::filesystem::directory_iterator (fullPath)) {
980
+ if (directoryEntry.is_regular_file ()) { filePaths->emplace_back (directoryEntry.path ().filename ().generic_string ()); }
981
+ }
982
+ }
947
983
}
948
984
return filePaths;
949
985
}
950
986
951
987
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
952
988
953
- bool LuaMan::FileExists (const std::string &fileName) {
954
- std::string fullPath = System::GetWorkingDirectory () + g_PresetMan.GetFullModulePath (fileName);
955
- if ((fullPath.find (" .." ) == std::string::npos) && (fullPath.find (System::GetModulePackageExtension ()) != std::string::npos)) {
956
- return std::filesystem::exists (fullPath);
989
+ bool LuaMan::FileExists (const std::string &path) {
990
+ std::string fullPath = System::GetWorkingDirectory () + g_PresetMan.GetFullModulePath (path);
991
+ if (IsValidModulePath (fullPath)) {
992
+ #ifndef _WIN32
993
+ fullPath = GetCaseInsensitiveFullPath (fullPath);
994
+ #endif
995
+ return std::filesystem::is_regular_file (fullPath);
957
996
}
997
+ return false ;
998
+ }
999
+
1000
+ // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
958
1001
1002
+ bool LuaMan::DirectoryExists (const std::string &path) {
1003
+ std::string fullPath = System::GetWorkingDirectory () + g_PresetMan.GetFullModulePath (path);
1004
+ if (IsValidModulePath (fullPath)) {
1005
+ #ifndef _WIN32
1006
+ fullPath = GetCaseInsensitiveFullPath (fullPath);
1007
+ #endif
1008
+ return std::filesystem::is_directory (fullPath);
1009
+ }
959
1010
return false ;
960
1011
}
961
1012
962
1013
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
963
1014
964
- int LuaMan::FileOpen (const std::string &fileName, const std::string &accessMode) {
1015
+ // TODO: Move to ModuleMan, once the ModuleMan PR has been merged
1016
+ bool LuaMan::IsValidModulePath (const std::string &path) {
1017
+ return (path.find (" .." ) == std::string::npos) && (path.find (System::GetModulePackageExtension ()) != std::string::npos);
1018
+ }
1019
+
1020
+ // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1021
+
1022
+ int LuaMan::FileOpen (const std::string &path, const std::string &accessMode) {
965
1023
if (c_FileAccessModes.find (accessMode) == c_FileAccessModes.end ()) {
966
1024
g_ConsoleMan.PrintString (" ERROR: Cannot open file, invalid file access mode specified." );
967
1025
return -1 ;
@@ -979,37 +1037,43 @@ namespace RTE {
979
1037
return -1 ;
980
1038
}
981
1039
982
- std::string fullPath = System::GetWorkingDirectory () + g_PresetMan.GetFullModulePath (fileName);
983
- if ((fullPath.find (" .." ) == std::string::npos) && (fullPath.find (System::GetModulePackageExtension ()) != std::string::npos)) {
984
-
1040
+ std::string fullPath = System::GetWorkingDirectory () + g_PresetMan.GetFullModulePath (path);
1041
+ if (IsValidModulePath (fullPath)) {
985
1042
#ifdef _WIN32
986
1043
FILE *file = fopen (fullPath.c_str (), accessMode.c_str ());
987
1044
#else
988
1045
FILE *file = [&fullPath, &accessMode]() -> FILE* {
989
1046
std::filesystem::path inspectedPath = System::GetWorkingDirectory ();
990
1047
const std::filesystem::path relativeFilePath = std::filesystem::path (fullPath).lexically_relative (inspectedPath);
991
1048
1049
+ // Iterate over all path parts
992
1050
for (std::filesystem::path::const_iterator relativeFilePathIterator = relativeFilePath.begin (); relativeFilePathIterator != relativeFilePath.end (); ++relativeFilePathIterator) {
993
1051
bool pathPartExists = false ;
994
1052
995
- // Check if a path part (directory or file) exists in the filesystem.
1053
+ // Iterate over all entries in the path part's directory,
1054
+ // to check if the path part is in there case insensitively
996
1055
for (const std::filesystem::path &filesystemEntryPath : std::filesystem::directory_iterator (inspectedPath)) {
997
- if (StringsEqualCaseInsensitive (filesystemEntryPath.filename ().generic_string (), (* relativeFilePathIterator). generic_string ())) {
1056
+ if (StringsEqualCaseInsensitive (filesystemEntryPath.filename ().generic_string (), relativeFilePathIterator-> generic_string ())) {
998
1057
inspectedPath = filesystemEntryPath;
1058
+
1059
+ // If the path part is found, stop looking for it
999
1060
pathPartExists = true ;
1000
1061
break ;
1001
1062
}
1002
1063
}
1064
+
1003
1065
if (!pathPartExists) {
1004
- // If this is the last part, then all directories in relativeFilePath exist, but the file doesn't.
1066
+ // If this is the last part, then all directories in relativeFilePath exist, but the file doesn't
1005
1067
if (std::next (relativeFilePathIterator) == relativeFilePath.end ()) {
1006
1068
return fopen ((inspectedPath / relativeFilePath.filename ()).generic_string ().c_str (), accessMode.c_str ());
1007
1069
}
1008
- // Some directory in relativeFilePath doesn't exist, so the file can't be created.
1070
+
1071
+ // Some directory in relativeFilePath doesn't exist, so the file can't be created
1009
1072
return nullptr ;
1010
1073
}
1011
1074
}
1012
- // If the file exists, open it.
1075
+
1076
+ // If the file exists, open it
1013
1077
return fopen (inspectedPath.generic_string ().c_str (), accessMode.c_str ());
1014
1078
}();
1015
1079
#endif
@@ -1018,7 +1082,7 @@ namespace RTE {
1018
1082
return fileIndex;
1019
1083
}
1020
1084
}
1021
- g_ConsoleMan.PrintString (" ERROR: Failed to open file " + fileName );
1085
+ g_ConsoleMan.PrintString (" ERROR: Failed to open file " + path );
1022
1086
return -1 ;
1023
1087
}
1024
1088
@@ -1039,6 +1103,112 @@ namespace RTE {
1039
1103
}
1040
1104
}
1041
1105
1106
+ // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1107
+
1108
+ bool LuaMan::FileRemove (const std::string& path) {
1109
+ std::string fullPath = System::GetWorkingDirectory () + g_PresetMan.GetFullModulePath (path);
1110
+ if (IsValidModulePath (fullPath)) {
1111
+ #ifndef _WIN32
1112
+ fullPath = GetCaseInsensitiveFullPath (fullPath);
1113
+ #endif
1114
+ if (std::filesystem::is_regular_file (fullPath)) {
1115
+ return std::filesystem::remove (fullPath);
1116
+ }
1117
+ }
1118
+ g_ConsoleMan.PrintString (" ERROR: Failed to remove file " + path);
1119
+ return false ;
1120
+ }
1121
+
1122
+ // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1123
+
1124
+ bool LuaMan::DirectoryCreate (const std::string& path, bool recursive) {
1125
+ std::string fullPath = System::GetWorkingDirectory () + g_PresetMan.GetFullModulePath (path);
1126
+ if (IsValidModulePath (fullPath)) {
1127
+ #ifndef _WIN32
1128
+ fullPath = GetCaseInsensitiveFullPath (fullPath);
1129
+ #endif
1130
+ try {
1131
+ if (recursive) {
1132
+ return std::filesystem::create_directories (fullPath);
1133
+ } else {
1134
+ return std::filesystem::create_directory (fullPath);
1135
+ }
1136
+ } catch (const std::filesystem::filesystem_error &e) {}
1137
+ }
1138
+ g_ConsoleMan.PrintString (" ERROR: Failed to remove directory " + path);
1139
+ return false ;
1140
+ }
1141
+
1142
+ // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1143
+
1144
+ bool LuaMan::DirectoryRemove (const std::string& path, bool recursive) {
1145
+ std::string fullPath = System::GetWorkingDirectory () + g_PresetMan.GetFullModulePath (path);
1146
+ if (IsValidModulePath (fullPath)) {
1147
+ #ifndef _WIN32
1148
+ fullPath = GetCaseInsensitiveFullPath (fullPath);
1149
+ #endif
1150
+ if (std::filesystem::is_directory (fullPath)) {
1151
+ try {
1152
+ if (recursive) {
1153
+ return std::filesystem::remove_all (fullPath) > 0 ;
1154
+ } else {
1155
+ return std::filesystem::remove (fullPath);
1156
+ }
1157
+ } catch (const std::filesystem::filesystem_error &e) {}
1158
+ }
1159
+ }
1160
+ g_ConsoleMan.PrintString (" ERROR: Failed to remove directory " + path);
1161
+ return false ;
1162
+ }
1163
+
1164
+ // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1165
+
1166
+ bool LuaMan::FileRename (const std::string& oldPath, const std::string& newPath) {
1167
+ std::string fullOldPath = System::GetWorkingDirectory () + g_PresetMan.GetFullModulePath (oldPath);
1168
+ std::string fullNewPath = System::GetWorkingDirectory () + g_PresetMan.GetFullModulePath (newPath);
1169
+ if (IsValidModulePath (fullOldPath) && IsValidModulePath (fullNewPath)) {
1170
+ #ifndef _WIN32
1171
+ fullOldPath = GetCaseInsensitiveFullPath (fullOldPath);
1172
+ fullNewPath = GetCaseInsensitiveFullPath (fullNewPath);
1173
+ #endif
1174
+ // Ensures parity between Linux which can overwrite an empty directory, while Windows can't
1175
+ // Ensures parity between Linux which can't rename a directory to a newPath that is a file in order to overwrite it, while Windows can
1176
+ if (std::filesystem::is_regular_file (fullOldPath) && !std::filesystem::exists (fullNewPath))
1177
+ {
1178
+ try {
1179
+ std::filesystem::rename (fullOldPath, fullNewPath);
1180
+ return true ;
1181
+ } catch (const std::filesystem::filesystem_error &e) {}
1182
+ }
1183
+ }
1184
+ g_ConsoleMan.PrintString (" ERROR: Failed to rename oldPath " + oldPath + " to newPath " + newPath);
1185
+ return false ;
1186
+ }
1187
+
1188
+ // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1189
+
1190
+ bool LuaMan::DirectoryRename (const std::string& oldPath, const std::string& newPath) {
1191
+ std::string fullOldPath = System::GetWorkingDirectory () + g_PresetMan.GetFullModulePath (oldPath);
1192
+ std::string fullNewPath = System::GetWorkingDirectory () + g_PresetMan.GetFullModulePath (newPath);
1193
+ if (IsValidModulePath (fullOldPath) && IsValidModulePath (fullNewPath)) {
1194
+ #ifndef _WIN32
1195
+ fullOldPath = GetCaseInsensitiveFullPath (fullOldPath);
1196
+ fullNewPath = GetCaseInsensitiveFullPath (fullNewPath);
1197
+ #endif
1198
+ // Ensures parity between Linux which can overwrite an empty directory, while Windows can't
1199
+ // Ensures parity between Linux which can't rename a directory to a newPath that is a file in order to overwrite it, while Windows can
1200
+ if (std::filesystem::is_directory (fullOldPath) && !std::filesystem::exists (fullNewPath))
1201
+ {
1202
+ try {
1203
+ std::filesystem::rename (fullOldPath, fullNewPath);
1204
+ return true ;
1205
+ } catch (const std::filesystem::filesystem_error &e) {}
1206
+ }
1207
+ }
1208
+ g_ConsoleMan.PrintString (" ERROR: Failed to rename oldPath " + oldPath + " to newPath " + newPath);
1209
+ return false ;
1210
+ }
1211
+
1042
1212
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1043
1213
1044
1214
std::string LuaMan::FileReadLine (int fileIndex) {
@@ -1096,15 +1266,15 @@ namespace RTE {
1096
1266
1097
1267
void LuaMan::StartAsyncGarbageCollection () {
1098
1268
ZoneScoped;
1099
-
1269
+
1100
1270
std::vector<LuaStateWrapper*> allStates;
1101
1271
allStates.reserve (m_ScriptStates.size () + 1 );
1102
1272
1103
1273
allStates.push_back (&m_MasterScriptState);
1104
1274
for (LuaStateWrapper& wrapper : m_ScriptStates) {
1105
1275
allStates.push_back (&wrapper);
1106
1276
}
1107
-
1277
+
1108
1278
m_GarbageCollectionTask = BS::multi_future<void >();
1109
1279
for (LuaStateWrapper* luaState : allStates) {
1110
1280
m_GarbageCollectionTask.push_back (
0 commit comments