2017-05-31 16:42:51 +00:00
#Preload Exception handler
import sys
def preloadExceptionHandler ( exc_type , exc_value , tb ) :
import traceback
print ( " An error has occurred while initializing: " )
traceback . print_exception ( exc_type , exc_value , tb )
input ( " \n Press ENTER to exit. " )
sys . exit ( - 1 )
2018-09-28 17:59:23 +00:00
#sys.excepthook = preloadExceptionHandler
2017-05-31 16:42:51 +00:00
#Imports and variables
2019-01-06 23:11:06 +00:00
class uml :
version = 0
2019-06-02 14:18:05 +00:00
versionSub = 8
2019-06-02 14:32:08 +00:00
versionSub2 = 1
2019-01-06 23:11:06 +00:00
versionBranch = " beta (dev) "
versionString = str ( version ) + " . " + str ( versionSub ) + " . " + str ( versionSub2 ) + " " + versionBranch
2018-11-27 23:32:15 +00:00
2017-05-25 17:31:36 +00:00
import ctypes
import os
import shutil
import webbrowser
2017-05-31 16:42:51 +00:00
import time
import stat
2017-07-03 02:18:30 +00:00
2017-05-31 16:42:51 +00:00
scriptPath = os . path . dirname ( os . path . realpath ( __file__ ) )
2017-07-03 02:18:30 +00:00
appPath = False
appName = False
originalAppPath = False
tmpAppPath = False
modPath = False
originalModPath = False
2019-06-02 14:31:56 +00:00
api = True
2017-05-25 17:31:36 +00:00
2017-05-31 16:42:51 +00:00
#Exception Handler
def openFileWithStandardApp ( path ) :
# Windows
if os . name == " nt " :
os . startfile ( path )
# Macintosh
elif sys . platform == " darwin " :
subprocess . call ( [ ' open ' , path ] )
# Generic Unix (X11)
else :
subprocess . call ( [ ' xdg-open ' , path ] )
2019-01-06 23:07:32 +00:00
def testAccess ( path ) :
try :
os . rename ( path , path )
return True
except :
return False
2017-07-21 12:23:23 +00:00
def exceptionCleanup ( ) :
success = True
2017-12-17 04:34:03 +00:00
print ( " Attempting cleanup. " )
print ( " \n Making folders visible... " )
2017-07-21 12:23:23 +00:00
try :
2018-09-28 18:00:14 +00:00
#ctypes.windll.kernel32.SetFileAttributesW(appPath,128)
#ctypes.windll.kernel32.SetFileAttributesW(originalAppPath,128)
pass
2017-07-21 12:23:23 +00:00
except Exception as e :
success = False
2017-12-17 04:34:03 +00:00
print ( str ( e ) )
2017-07-21 12:23:23 +00:00
2017-12-17 04:34:03 +00:00
print ( " \n Unloading mods... " )
2017-07-21 12:23:23 +00:00
try :
unloadMods ( )
except Exception as e :
success = False
2017-12-17 04:34:03 +00:00
print ( str ( e ) )
2017-07-21 12:23:23 +00:00
2017-12-17 04:34:03 +00:00
print ( " \n Cleaning up temporary files... " )
2017-07-21 12:23:23 +00:00
try :
cleanUp ( )
except Exception as e :
success = False
2017-12-17 04:34:03 +00:00
print ( str ( e ) )
2017-07-21 12:23:23 +00:00
if success == False :
2017-12-17 04:34:03 +00:00
print ( " \n Cleanup not fully successful. Please review the errors, and go to X for a guide on how to reset your game manually. Sorry for the inconvenience, I tried :( " )
2017-07-21 12:23:23 +00:00
2017-12-17 04:34:03 +00:00
return success
2017-07-21 12:23:23 +00:00
2017-08-16 13:09:53 +00:00
def logError ( logFilePath , textList ) :
logFile = False
2017-07-21 12:23:23 +00:00
2017-08-16 13:09:53 +00:00
try :
logFile = open ( logFilePath , " w " )
except :
return False
try :
for line in textList :
logFile . write ( line + " \n " )
except :
logFile . close ( )
return False
logFile . close ( )
return True
2017-05-31 16:42:51 +00:00
def exceptionHandler ( exc_type , exc_value , tb ) :
2017-08-16 13:09:53 +00:00
clear ( )
print ( " An error occurred, trying to revert everything... " )
2017-12-17 04:34:03 +00:00
exceptionCleanup ( )
input ( )
2017-07-21 12:23:23 +00:00
2018-09-28 17:59:23 +00:00
#sys.excepthook = exceptionHandler
2017-05-31 16:42:51 +00:00
#Modloader
def cloneMods ( modDir ) :
for root , dirs , files in walklevel ( modDir , 0 ) :
for dir in dirs :
if dir [ 0 ] == " - " : continue
if dir [ 0 ] == " [ " and dir [ - 1 : ] == " ] " :
cloneMods ( os . path . join ( root , dir ) )
else :
2017-12-17 04:34:03 +00:00
print ( " Applying Mod: " + dir )
2017-07-03 03:28:02 +00:00
if os . path . isfile ( os . path . join ( root , dir , " uml_installscript.py " ) ) == True :
file = open ( os . path . join ( root , dir , " uml_installscript.py " ) )
exec ( file . read ( ) , globals ( ) , locals ( ) )
file . close ( )
else :
cloneFolder ( os . path . join ( root , dir ) , tmpAppPath , True , False , True )
2017-05-31 16:42:51 +00:00
2018-09-28 18:02:05 +00:00
def loadMods ( output = False , fast = False ) :
if fast == False :
if areModsLoaded ( ) :
if unloadMods ( ) == False :
if output : print ( " Unloading mods failed! " )
return False
2017-05-25 17:31:36 +00:00
2018-09-28 18:02:05 +00:00
if fast == True :
if areModsLoaded ( ) == False :
if output : print ( " Can not fast-load mods when mods aren ' t loaded. " )
return False
2017-05-25 17:31:36 +00:00
2018-09-28 18:02:05 +00:00
if fast == False :
2018-12-29 03:30:58 +00:00
if areModsLoaded ( ) :
if output : print ( " Mods are already loaded and could not be unloaded. " )
return False
2019-06-02 14:17:53 +00:00
#print("Claiming app folder...")
#claimFolder(appPath)
#print("Claiming mod folder...")
#claimFolder(modPath)
2018-12-29 03:30:58 +00:00
print ( " Testing access... " )
2019-01-06 23:07:32 +00:00
if testAccess ( appPath ) == False :
2018-12-29 03:30:58 +00:00
if output : print ( " Can ' t access folder! Is it in use? " )
return
2018-09-28 18:02:05 +00:00
print ( " Cloning app folder... " )
cloneFolder ( appPath , tmpAppPath , False )
2018-12-29 03:30:58 +00:00
2018-09-28 18:02:05 +00:00
print ( " Cloning mods... " )
cloneMods ( modPath )
os . rename ( appPath , originalAppPath )
os . rename ( tmpAppPath , appPath )
else :
2018-12-29 03:30:58 +00:00
print ( " Testing access... " )
2019-01-06 23:07:32 +00:00
if testAccess ( appPath ) == False :
2018-12-29 03:30:58 +00:00
if output : print ( " Can ' t access folder! Is it in use? " )
return
2018-09-28 18:02:05 +00:00
os . rename ( appPath , tmpAppPath )
cloneMods ( modPath )
os . rename ( tmpAppPath , appPath )
2018-09-28 18:00:14 +00:00
#ctypes.windll.kernel32.SetFileAttributesW(originalAppPath,2)
2017-05-25 17:31:36 +00:00
2017-12-17 04:34:03 +00:00
if output : print ( " \n Mods have been loaded! " )
2017-05-25 17:31:36 +00:00
return True
def unloadMods ( output = False ) :
if areModsLoaded ( ) == False :
if output : print ( " Mods are already unloaded. " )
return True
2018-12-29 03:30:58 +00:00
print ( " Testing access... " )
2019-01-06 23:07:32 +00:00
if testAccess ( appPath ) == False :
2018-12-29 03:30:58 +00:00
if output : print ( " Can ' t access folder! Is it in use? " )
return
2017-12-17 04:34:03 +00:00
print ( " Removing cloned app folder... " )
2019-01-06 23:14:18 +00:00
try :
shutil . rmtree ( appPath )
except :
if output : print ( " Can ' t delete folder! Is it in use? " )
return
2019-01-06 23:20:17 +00:00
tries = 0
while tries < 100 :
try :
os . rename ( originalAppPath , appPath )
tries + 1
except :
time . sleep ( 0.1 )
2019-01-07 03:33:31 +00:00
tries + 1
2019-01-06 23:20:17 +00:00
else :
2019-01-07 03:33:31 +00:00
break
2019-01-06 23:20:17 +00:00
2018-09-28 18:00:14 +00:00
#ctypes.windll.kernel32.SetFileAttributesW(appPath,128)
2017-05-25 17:31:36 +00:00
2017-12-17 04:34:03 +00:00
if output : print ( " \n Unloading mods successful. " )
2017-05-25 17:31:36 +00:00
return True
def openModsFolder ( ) :
if areModsLoaded ( ) :
webbrowser . open ( " file:/// " + originalModPath )
else :
webbrowser . open ( " file:/// " + modPath )
def areModsLoaded ( ) :
if os . path . isdir ( originalAppPath ) :
return True
return False
2017-12-17 04:34:03 +00:00
def cloneFolder ( src , dst , rpl , ignoreMods = True , isMod = False ) :
2018-11-03 10:56:00 +00:00
maxCount = 0
count = 0
for root , dirs , files in os . walk ( src ) :
newRoot = root . replace ( src , dst )
if ignoreMods == True :
if root . replace ( modPath , " " ) != root : continue
maxCount = maxCount + len ( files )
sys . stdout . write ( " \r " + str ( count ) + " / " + str ( maxCount ) )
sys . stdout . flush ( )
2017-05-25 17:31:36 +00:00
for root , dirs , files in os . walk ( src ) :
newRoot = root . replace ( src , dst )
if ignoreMods == True :
if root . replace ( modPath , " " ) != root : continue
if os . path . isdir ( newRoot ) == False : os . makedirs ( newRoot )
for file in files :
2018-11-03 10:56:00 +00:00
count = count + 1
sys . stdout . write ( " \r " + str ( count ) + " / " + str ( maxCount ) )
sys . stdout . flush ( )
2017-07-03 03:28:02 +00:00
if isMod == True :
if file [ : 4 ] == " uml_ " : continue
2017-05-25 17:31:36 +00:00
fullFile = os . path . join ( root , file )
newFile = os . path . join ( newRoot , file )
if os . path . isfile ( newFile ) :
if rpl == True :
os . remove ( newFile )
os . link ( fullFile , newFile )
else :
os . link ( fullFile , newFile )
2018-11-03 10:56:00 +00:00
print ( " " )
2017-05-25 17:31:36 +00:00
2017-05-31 16:42:51 +00:00
def claimFolder ( path ) :
os . chmod ( path , stat . S_IRWXU | stat . S_IRWXG | stat . S_IRWXO )
2017-12-17 04:34:03 +00:00
for root , dirs , files in os . walk ( path ) :
for dir in dirs :
os . chmod ( os . path . join ( root , dir ) , stat . S_IRWXU | stat . S_IRWXG | stat . S_IRWXO )
for file in files :
os . chmod ( os . path . join ( root , file ) , stat . S_IRWXU | stat . S_IRWXG | stat . S_IRWXO )
2017-05-31 16:42:51 +00:00
2017-05-25 17:31:36 +00:00
def walklevel ( some_dir , level = 1 ) :
some_dir = some_dir . rstrip ( os . path . sep )
assert os . path . isdir ( some_dir )
num_sep = some_dir . count ( os . path . sep )
for root , dirs , files in os . walk ( some_dir ) :
yield root , dirs , files
num_sep_this = root . count ( os . path . sep )
if num_sep + level < = num_sep_this :
del dirs [ : ]
def title ( string ) :
2019-06-02 14:31:56 +00:00
if api == True : return
2017-05-25 17:31:36 +00:00
if os . name == " nt " :
os . system ( " title " + string )
else :
sys . stdout . write ( " \x1b ]2; " + string + " \x07 " )
def clear ( ) :
os . system ( ' cls ' if os . name == ' nt ' else ' clear ' )
def cleanUp ( ) :
if os . path . isdir ( tmpAppPath ) :
shutil . rmtree ( tmpAppPath )
def checkUp ( ) :
2017-12-17 04:34:03 +00:00
if os . path . isdir ( modPath ) == False :
while True :
clear ( )
print ( " You selected the following path: ' " + appPath + " ' " )
choice = input ( " Do you wish to set up that folder for mod-use? (y/n) \n " )
if choice == " y " :
os . makedirs ( modPath )
2018-09-28 18:00:14 +00:00
#ctypes.windll.kernel32.SetFileAttributesW(modPath,2)
2017-12-17 04:34:03 +00:00
return
2017-07-21 12:23:23 +00:00
2017-12-17 04:34:03 +00:00
if choice == " n " : sys . exit ( - 1 )
2017-05-25 17:31:36 +00:00
def mainMenu ( ) :
clear ( )
if areModsLoaded ( ) == False :
print ( " Welcome to Fier ' s Universal Modloader. " )
print ( " Mods are not loaded. " )
print ( " " )
print ( " Please choose an action: " )
print ( " 1) Load Mods " )
print ( " 2) Open Mods-Folder " )
choice = input ( " Choice: " )
clear ( )
if choice == " 1 " : loadMods ( True ) ; input ( " Press ENTER to continue. " )
if choice == " 2 " : openModsFolder ( )
else :
print ( " Welcome to Fier ' s Universal Modloader. " )
print ( " Mods are loaded. " )
print ( " " )
print ( " Please choose an action: " )
print ( " 1) Reload Mods " )
2018-09-28 18:02:05 +00:00
print ( " 2) Fast-Load Mods " )
print ( " 3) Unload Mods " )
print ( " 4) Open Mods-Folder " )
2017-05-25 17:31:36 +00:00
choice = input ( " Choice: " )
clear ( )
if choice == " 1 " : loadMods ( True ) ; input ( " Press ENTER to continue. " )
2018-09-28 18:02:05 +00:00
if choice == " 2 " : loadMods ( True , True ) ; input ( " Press ENTER to continue. " )
if choice == " 3 " : unloadMods ( True ) ; input ( " Press ENTER to continue. " )
if choice == " 4 " : openModsFolder ( )
2017-05-25 17:31:36 +00:00
2017-07-21 08:19:16 +00:00
def requestAppPath ( ) :
while True :
clear ( )
dir = input ( " Please insert a folder via Drag&Drop: \n " )
2019-06-02 14:16:15 +00:00
if ( dir [ 0 ] == ' " ' and dir [ - 1 ] == ' " ' ) or ( dir [ 0 ] == " ' " and dir [ - 1 ] == " ' " ) : dir = dir [ 1 : - 1 ]
2018-11-28 00:16:25 +00:00
if dir == " console " :
console ( )
else :
if os . path . isdir ( dir ) == True :
return dir
def console ( ) :
clear ( )
print ( " UniversalModloader Console " )
2019-01-06 23:11:06 +00:00
print ( " Version: " + uml . versionString )
2018-11-28 00:16:25 +00:00
while True :
2019-01-06 22:11:27 +00:00
print ( " " )
2018-11-28 00:16:25 +00:00
cmd = input ( os . getcwd ( ) + " > " )
2018-11-28 01:16:51 +00:00
if cmd == " exit " :
return
2019-01-06 22:12:34 +00:00
if cmd . startswith ( " cd " ) :
try :
os . chdir ( cmd [ 3 : ] )
continue
except Exception as e :
print ( e )
continue
continue
2018-11-28 00:16:25 +00:00
if cmd . startswith ( " pyc " ) :
try :
exec ( cmd [ 4 : ] )
2019-01-06 22:12:34 +00:00
continue
2018-11-28 00:16:25 +00:00
except Exception as e :
print ( e )
2019-01-06 22:12:34 +00:00
continue
if cmd . startswith ( " mc " ) :
try :
cloneFolder ( cmd [ 3 : ] , cmd [ 3 : ] + " - clone " , True , False )
continue
except Exception as e :
print ( e )
continue
2018-11-28 00:16:25 +00:00
2019-01-06 22:12:34 +00:00
os . system ( cmd )
2017-07-21 08:19:16 +00:00
2017-07-03 02:18:30 +00:00
def setupVariables ( ) :
global appPath
global appName
global originalAppPath
global tmpAppPath
global modPath
global originalModPath
2017-07-21 08:19:16 +00:00
if len ( sys . argv ) < 2 :
appPath = requestAppPath ( )
else :
appPath = sys . argv [ 1 ]
2018-11-28 00:16:25 +00:00
if appPath == " console " :
console ( )
2017-07-21 08:19:16 +00:00
if os . path . isdir ( appPath ) == False :
raise NameError ( " Folder not found: " + appPath )
2017-07-03 02:18:30 +00:00
if os . path . isdir ( appPath . replace ( " - umlOriginal " , " " ) ) : appPath = appPath . replace ( " - umlOriginal " , " " )
2019-06-02 14:16:15 +00:00
appName = appPath . replace ( os . path . dirname ( appPath ) + os . sep , " " )
2017-07-03 02:18:30 +00:00
originalAppPath = appPath + " - umlOriginal "
tmpAppPath = appPath + " - umlTemp "
2017-12-17 04:34:03 +00:00
modPath = os . path . join ( appPath + " - umlMods " )
originalModPath = modPath
2017-07-03 02:18:30 +00:00
2019-06-02 14:31:56 +00:00
def init ( ) :
2019-06-02 15:56:01 +00:00
global api
2019-06-02 14:31:56 +00:00
api = False
title ( " Fier ' s Universal Modloader - " + uml . versionString )
setupVariables ( )
title ( " Fier ' s Universal Modloader - " + uml . versionString + " : " + appName )
2017-07-03 02:18:30 +00:00
2019-06-02 14:31:56 +00:00
cleanUp ( )
checkUp ( )
2017-12-17 04:34:03 +00:00
2019-06-02 14:31:56 +00:00
while True :
mainMenu ( )
if __name__ == " __main__ " :
init ( )