@@ -151,15 +151,11 @@ def dataLooksValid(
151151 GameDataMovies = getattr (self .organizer .managedGame (), "GameDataMovies" , "" )
152152 if filetree .exists (GameDataPakMods , mobase .IFileTree .DIRECTORY ):
153153 return mobase .ModDataChecker .VALID
154- if filetree .exists (
155- os .path .dirname (GameDataUE4SSMods ), mobase .IFileTree .DIRECTORY
156- ):
154+ if filetree .exists (GameDataMovies , mobase .IFileTree .DIRECTORY ):
157155 return mobase .ModDataChecker .VALID
158- if filetree .exists (
159- GameDataNativeMods , mobase .IFileTree .DIRECTORY
160- ) and not filetree .exists ("UE4SS.dll" , mobase .IFileTree .FILE ):
156+ if filetree .exists (GameDataUE4SSMods , mobase .IFileTree .DIRECTORY ):
161157 return mobase .ModDataChecker .VALID
162- if filetree .exists (GameDataMovies , mobase .IFileTree .DIRECTORY ):
158+ if filetree .exists (GameDataNativeMods , mobase .IFileTree .DIRECTORY ):
163159 return mobase .ModDataChecker .VALID
164160 return mobase .ModDataChecker .FIXABLE
165161
@@ -256,72 +252,69 @@ def collectModCandidates(
256252 category = None
257253 entryext = "None"
258254
255+ GameDataUE4SSRootDir = getattr (
256+ self .organizer .managedGame (), "GameDataUE4SSMods" , ""
257+ )
258+ GameDataPakModsDir = getattr (
259+ self .organizer .managedGame (), "GameDataPakMods" , ""
260+ )
261+ GameDataNativeModsDir = getattr (
262+ self .organizer .managedGame (), "GameDataNativeMods" , ""
263+ )
264+ GameDataMoviesDir = getattr (self .organizer .managedGame (), "GameDataMovies" , "" )
265+
259266 if installtype == "os" and isinstance (tree , mobase .IFileTree ):
260267 for entry in tree :
261268 entryext = os .path .splitext (entry .name ())[1 ].removeprefix ("." )
262269 else :
263270 entryext = tree .suffix ().casefold ()
264271
265- if (
266- tree .exists ("UE4SS.dll" , mobase .IFileTree .FILE )
267- or tree .exists ("Scripts" , mobase .IFileTree .DIRECTORY )
268- or tree .exists ("dlls" , mobase .IFileTree .DIRECTORY )
269- or tree .exists ("Binaries" , mobase .IFileTree .DIRECTORY )
270- ):
271- category = "UE4SS"
272- elif tree .exists ("Content/Paks" , mobase .IFileTree .DIRECTORY ):
273- category = "Paks"
274- elif tree .exists ("Content/Movies" , mobase .IFileTree .DIRECTORY ):
275- category = "Movie"
276- elif tree .exists ("Content" , mobase .IFileTree .DIRECTORY ):
277- category = "Native"
278- else :
279- for entry in tree :
280- if entry .isFile ():
281- suffix = entry .suffix ().casefold ()
282- if suffix in {"pak" , "utoc" , "ucas" }:
283- category = "Paks"
284- break
285- if suffix == "bk2" :
286- category = "Movie"
287- break
288- if suffix in {"dll" , "lua" }:
289- category = "UE4SS"
290- break
291-
292- if category is None :
293- match entryext :
294- case "pak" | "utoc" | "ucas" :
295- category = "Paks"
296- case "bk2" :
297- category = "Movie"
298- case _:
299- pass
272+ # Check for UE4SS installations
273+ if isinstance (tree , mobase .IFileTree ) and tree .isDir ():
274+ if tree .exists ("ue4ss.dll" , mobase .IFileTree .FILE ) or tree .exists (
275+ "dsound.dll" , mobase .IFileTree .FILE
276+ ):
277+ category = "Root"
278+ elif tree .exists ("Scripts" , mobase .IFileTree .DIRECTORY ) and not tree .exists (
279+ "UE4SS.dll" , mobase .IFileTree .FILE
280+ ):
281+ disallowedFolders = {"mods" }
282+ tree_path = tree .path ()
283+ tree_path_lower = tree_path .replace ("\\ " , "/" ).casefold ()
284+ if not disallowedFolders & set (tree_path_lower .split ("/" )):
285+ category = "UE4SS"
286+ elif tree .exists ("Content" , mobase .IFileTree .DIRECTORY ):
287+ category = "Native"
288+
289+ # Check single file for correct extensions
290+ match entryext :
291+ case "pak" | "utoc" | "ucas" :
292+ category = "Paks"
293+ case "bk2" :
294+ category = "Movie"
295+ case _:
296+ pass
300297
301298 if category is None :
302299 return False
303300
304301 if category == "UE4SS" :
305- destination = (
306- getattr ( self . organizer . managedGame (), "GameDataUE4SSMods" , "" ) + "/"
307- )
302+ destination = GameDataUE4SSRootDir + "/"
303+ elif category == "Root" :
304+ destination = GameDataUE4SSRootDir + "/"
308305 elif category == "Paks" :
309- destination = (
310- getattr (self .organizer .managedGame (), "GameDataPakMods" , "" ) + "/"
311- )
306+ destination = GameDataPakModsDir + "/"
312307 elif category == "Movie" :
313- destination = (
314- getattr ( self . organizer . managedGame (), "GameDataMovies" , "" ) + "/"
315- )
308+ destination = GameDataMoviesDir + "/"
309+ elif category == "Native" :
310+ destination = GameDataNativeModsDir + "/"
316311 else :
317- destination = (
318- getattr (self .organizer .managedGame (), "GameDataNativeMods" , "" ) + "/"
319- )
312+ destination = "/"
320313
321314 self .addModDetectionCandidate (
322315 tree ,
323316 sanitized_name ,
324- category ,
317+ f" { category } Mod" ,
325318 destination ,
326319 installtype ,
327320 )
@@ -354,6 +347,7 @@ def fix(self, filetree: mobase.IFileTree) -> mobase.IFileTree | None:
354347 self .modDetectionCandidates = []
355348 newtree = filetree .createOrphanTree ("Fixed Tree" )
356349
350+ # Check for Non Zipped Mod
357351 if filetree .name () != "" :
358352 self .collectModCandidates (filetree , installtype = "os" )
359353 else :
@@ -376,93 +370,18 @@ def fix(self, filetree: mobase.IFileTree) -> mobase.IFileTree | None:
376370 candidate ["destination" ],
377371 )
378372
379- if len ( newtree ) > 0 :
373+ if newtree :
380374 return newtree
381375
382- GameDataUE4SSMods = (
383- getattr (self .organizer .managedGame (), "GameDataUE4SSMods" , "" ) + "/"
384- )
385- GameDataPakMods = (
386- getattr (self .organizer .managedGame (), "GameDataPakMods" , "" ) + "/"
387- )
388- GameDataNativeMods = (
389- getattr (self .organizer .managedGame (), "GameDataNativeMods" , "" ) + "/"
390- )
391- GameDataMovies = (
392- getattr (self .organizer .managedGame (), "GameDataMovies" , "" ) + "/"
376+ # Fallback: Handle native mods with FOLDERNAME substitution
377+ GameDataNativeMods = getattr (
378+ self .organizer .managedGame (), "GameDataNativeMods" , ""
393379 )
394- treefixed = 0
395- if filetree .exists ("UE4SS.dll" , mobase .IFileTree .FILE ):
396- treefixed = self .allMoveTo (
397- filetree , os .path .dirname (os .path .dirname (GameDataUE4SSMods )) + "/"
398- )
399- if treefixed == 1 :
400- return filetree
401380 if filetree .exists ("Content" , mobase .IFileTree .DIRECTORY ):
402- treefixed = self .allMoveTo (filetree , GameDataNativeMods + "FOLDERNAME/" )
403- if treefixed == 1 :
404- self .needsNameFix = True
405- if self .fileExistsInNextSubDir (filetree , "Content" ):
406- filetree .move (filetree [0 ], GameDataNativeMods + "/" , mobase .IFileTree .MERGE )
407- treefixed = 1
408- if treefixed == 0 :
409- allowedUnzippedExt = ["pak" , "utoc" , "ucas" , "bk2" , "dll" ]
410- entriesToMove : list [mobase .FileTreeEntry ] = []
411- for e in filetree :
412- if e .isFile ():
413- fileext = e .suffix ().casefold ()
414- if fileext in allowedUnzippedExt :
415- mod_name = filetree .name ()
416- if mod_name == "" :
417- mod_name = e .name ()
418- mod_path = os .path .join (self .organizer .modsPath (), mod_name )
419- if not filetree .createOrphanTree (
420- "OrphanTree"
421- ) and os .path .exists (mod_path ):
422- match e .suffix ().casefold ():
423- case "pak" | "utoc" | "ucas" :
424- os .makedirs (
425- os .path .join (mod_path , GameDataPakMods ),
426- exist_ok = True ,
427- )
428- shutil .move (
429- os .path .join (mod_path , e .name ()),
430- os .path .join (
431- mod_path , GameDataPakMods , e .name ()
432- ),
433- )
434- case "bk2" :
435- os .makedirs (
436- os .path .join (mod_path , GameDataMovies ),
437- exist_ok = True ,
438- )
439- shutil .move (
440- os .path .join (mod_path , e .name ()),
441- os .path .join (
442- mod_path , GameDataMovies , e .name ()
443- ),
444- )
445- case _:
446- pass
447- treefixed = 1
448- else :
449- entriesToMove .append (e )
450- if entriesToMove :
451- for e in entriesToMove :
452- match e .suffix ().casefold ():
453- case "pak" | "utoc" | "ucas" :
454- filetree .move (e , GameDataPakMods , mobase .IFileTree .MERGE )
455- case "dll" :
456- filetree .move (
457- e ,
458- os .path .dirname (GameDataUE4SSMods ) + "/" ,
459- mobase .IFileTree .MERGE ,
460- )
461- case "bk2" :
462- filetree .move (e , GameDataMovies , mobase .IFileTree .MERGE )
463- case _:
464- pass
465- treefixed = 1
381+ self .needsNameFix = True
382+ self .allMoveTo (filetree , GameDataNativeMods + "/FOLDERNAME/" )
383+ return filetree
384+
466385 return filetree
467386
468387
0 commit comments