SHARE
TWEET

c3mm.py

7163D Oct 3rd, 2016 (edited) 133 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # Cossacks 3 (Text) Mod Manager version 1.3.1
  2. # Require python 3.5.x to work : https://python.org/downloads
  3. # Get all update at http://www.cossacks3.com/forum/index.php?threads/cossacks-3-text-mod-manager.17753
  4.  
  5. """
  6. # === News in 1.3.1 === #
  7.     >Change functionement of file-check. Now, if a file is modified, the program will test instalation of mods, and if mod are affected it uninstall it.
  8. """
  9.  
  10.  
  11. """
  12. Structur uses
  13. Mod  := {'name':name, 'version':version, 'info':info, 'file':{name => list of (str old, str new)}}
  14. Data := {'mod':{name => mod mod}, 'file':{name => list of str mod}}
  15. """
  16.  
  17. import json, sys, os, time
  18. from random import randrange
  19.  
  20. CONFIG_PATH = "c3mm/"
  21. MOD_PATH    = "mod/"
  22. COPY_PATH   = "c3mm/copy/"
  23. BCKUP_PATH  = "c3mm/bckup/"
  24. INFO_PATH   = "c3mm/c3mm.json"
  25. LOG_PATH    = "c3mm/log.txt"
  26. HELP = """
  27. Cossacks3 (text) Mod Manager Version 1.3.0.
  28. Type python c3mm.py action [parameter]
  29.     action:
  30.         install modname   -> intall a mod find by name
  31.         uninstall modname -> unintall a mod find by name
  32.         help              -> show this message
  33.         uninstall_all     -> uninstall all mod
  34. """
  35.  
  36. PATH = [CONFIG_PATH, MOD_PATH, COPY_PATH, BCKUP_PATH]
  37. FILE = [INFO_PATH, LOG_PATH]
  38. for path in PATH:
  39.     try:
  40.         os.mkdir(path)
  41.     except:
  42.         pass
  43. for file in FILE:
  44.     try:
  45.         open(file, 'r')
  46.     except:
  47.         open(file, 'w')
  48.  
  49. class Alert:
  50.     linfo = []
  51.     lerror = []
  52.  
  53.     def info(i):
  54.         Alert.linfo.append(i)
  55.         print(i)
  56.  
  57.     def error(e, data):
  58.         Alert.lerror.append(e)
  59.         print(e)
  60.         quit(data)
  61.  
  62.     def input(m):
  63.         return input(m)
  64.  
  65.     def list(l):
  66.         for i in l:
  67.             print(i)
  68.  
  69. def loadjson(path):
  70.     return json.loads(open(path, 'r').read())
  71.  
  72. def savejson(path, data):
  73.     open(path, "w").write(json.dumps(data))
  74.  
  75. def mkPath(path):
  76.     rpath = ""
  77.     for dir in path.split('/')[:-1]:
  78.         rpath += dir
  79.         try:
  80.             os.mkdir(rpath)
  81.         except:
  82.             pass
  83.         rpath += '/'
  84.  
  85. def copyFile(file, path):
  86.     mkPath(path)
  87.     open(path, "w").write(open(file, 'r').read())
  88.  
  89. def checkMod(mod):
  90.     """
  91.     checkMod function, use to check if a mod is valid
  92.     Mod mod     -> mod to check
  93.     Bool return -> is the mod valid?
  94.     """
  95.     for file in mod['file']:
  96.         Alert.info("Check existence of '" + file + "'")
  97.         try:
  98.             f = open(file, 'r').read()
  99.             Alert.info("'" + file + "' exist.")
  100.         except:
  101.             Alert.info("'" + file + "' don't exist.")
  102.             return False
  103.  
  104.         for old in mod['file'][file]:
  105.             Alert.info("Check exsitence of '" + old + "' in '" + file + "'")
  106.             if not old in f:
  107.                 Alert.info("Not found.")
  108.                 return False
  109.             else:
  110.                 Alert.info("Found.")
  111.     return True
  112.  
  113. def apply(mod):
  114.     """
  115.     apply function, use to modify files
  116.     Mod mod -> mod that contain all modifications
  117.     None return
  118.     """
  119.     mfile = {}
  120.     for file in mod['file']:
  121.         Alert.info("Patching '" + file + '"')
  122.         f = open(file, 'r').read()
  123.  
  124.         #Calculate modifications
  125.         for old in mod['file'][file]:
  126.             new = mod['file'][file][old]
  127.             f = f.replace(old, new)
  128.  
  129.         mfile[file] = f
  130.    
  131.     #Apply mod
  132.     for file in mfile:
  133.         open(file, 'w').write(mfile[file])
  134.  
  135. def install(mod, data):
  136.     """
  137.     install function, use to add a mod.
  138.     Mod mod   -> mod to install
  139.     Data data -> c3mm main data
  140.     None return
  141.     """
  142.     if not checkMod(mod):
  143.         Alert.error("'" + mod['name'] + "' mod version " + mod['version'] + " isn't valid", data)
  144.  
  145.     Alert.info("Install '" + mod['name'] + "' version " + mod['version'])
  146.  
  147.     #Add some "signature"
  148.     for file in mod['file']:
  149.         for old in mod['file'][file]:
  150.             mod['file'][file][old] = mod['file'][file][old] + "//" + str(randrange(100000, 999999))
  151.  
  152.     #Add mod to list of installed mod
  153.     data['mod'][mod['name']] = mod
  154.  
  155.     #Adding mod in list of file modification
  156.     for file in mod['file']:
  157.         if not file in data['file']:
  158.             data['file'][file] = [mod['name']]
  159.             #backup file
  160.             copyFile(file, BCKUP_PATH + file)
  161.         else:
  162.             data['file'][file].append(mod['name'])
  163.  
  164.     apply(mod)
  165.  
  166.     for file in mod['file']:
  167.         #make a save of the file
  168.         copyFile(file, COPY_PATH + file)
  169.  
  170. def uninstall(mod, data):
  171.     """
  172.     uninstall function, use to delete a mod.
  173.     Mod mod   -> mod to uninstall
  174.     Data data -> c3mm main data
  175.     None return
  176.     """
  177.     uninstallmod = mkuninstallmod(mod)
  178.  
  179.     if not checkMod(uninstallmod):
  180.         Alert.info("'" + mod['name'] + "' mod uninstaller isn't valid.")
  181.         Alert.info("Do you want restore all files concerned by this mod?")
  182.         Alert.info("List of mod will uninstalled in this case:")
  183.         modlist = []
  184.         for file in mod['file']:
  185.             for mod in data['file'][file]:
  186.                 if not mod in modlist:
  187.                     modlist.append(mod)
  188.                     Alert.info(mod)
  189.         choice = Alert.chocie("Restore all file? yes/no:")
  190.         if choice == 'no':
  191.             quit(data)
  192.  
  193.         filelist = [file for file in mod['file']]
  194.         for file in filelist:
  195.             Alert("Restore '" + file + "'")
  196.             copyFile(BCKUP_PATH + file, file)
  197.             data['mod'][mod]['file'].remove(file)
  198.  
  199.         for mod in modlist():
  200.             uninstall(mod, data)
  201.  
  202.        
  203.  
  204.     #Delete mod to list of installed mod
  205.     del data['mod'][mod['name']]
  206.  
  207.     #Delete mod of list of file modification
  208.     for file in data['file']:
  209.         if mod['name'] in data['file'][file]:
  210.             data['file'][file].remove(mod['name'])
  211.  
  212.     Alert.info("Uninstall '" + mod['name'] + "' version " + mod['version'])
  213.  
  214.     apply(uninstallmod)
  215.  
  216. def mkuninstallmod(mod):
  217.     """
  218.     mkuninstallmod function, use to make an uninstalator from a mod
  219.     Mod mod    -> mod to uninstall
  220.     Mod return -> uninstalator mod
  221.     """
  222.     uninstallmod = {}
  223.     uninstallmod['file'] = {}
  224.  
  225.     for file in mod['file']:
  226.         uninstallmod['file'][file] = {}
  227.         for old in mod['file'][file]:
  228.             new = mod['file'][file][old]
  229.             #For each modification of mod, inverse new and old
  230.             uninstallmod['file'][file][new] = old
  231.  
  232.     return uninstallmod
  233.  
  234. def checkStatu(data):
  235.     """
  236.     checkStatu funtion, check if a modded file has been modified since last launch of this program
  237.     Data data   -> main data
  238.     Bool return ->
  239.     """
  240.     badfile = []
  241.     #Check all modded file
  242.     for file in data['file']:
  243.         if open(file, 'r').read() != open(COPY_PATH + file, 'r').read():
  244.             Alert.info("File '" + file + "' has been modified since last launch of c3mm.")
  245.             badfile.append(file)
  246.  
  247.     badmod = []
  248.     #Uninstall all mod concerned by these files
  249.     for file in badfile:
  250.         for mod in data['file'][file]:
  251.             if not mod in badmod and not checkMod(mkuninstallmod(data['mod'][mod])):
  252.                 badmod.append(mod)
  253.  
  254.     for mod in badmod:
  255.         _mod = data['mod'][mod]
  256.         for file in badfile:
  257.             if file in _mod['file']:
  258.                 del _mod['file'][file]
  259.         uninstall(_mod, data)
  260.  
  261.     return len(badmod) == 0
  262.  
  263. def quit(data):
  264.  
  265.     dfile = []
  266.     for file in data['file']:
  267.         if data['file'][file] == []:
  268.             dfile.append(file)
  269.  
  270.     for file in dfile:
  271.         del data['file'][file]
  272.  
  273.     savejson(INFO_PATH, data)
  274.  
  275.     logs = time.strftime('%D %H:%M\n',time.localtime())
  276.     for info in Alert.linfo:
  277.         logs += info + '\n'
  278.     for error in Alert.lerror:
  279.         logs += error + '\n'
  280.  
  281.     open(LOG_PATH, "a").write(logs)
  282.     exit()
  283.  
  284. def main(argc, argv):
  285.  
  286.     try:
  287.         data = loadjson(INFO_PATH)
  288.     except:
  289.         open(INFO_PATH, "w").write('{"mod":{}, "file":{}}')
  290.         data = loadjson(INFO_PATH)
  291.  
  292.     if not checkStatu(data):
  293.         quit(data)
  294.  
  295.     elif argc == 1 or argv[1] == "help":
  296.         print(HELP)
  297.  
  298.     elif argv[1] == 'install':
  299.  
  300.         if argc < 3:
  301.             Alert.error("You must give a mod name", data)
  302.  
  303.         mod = loadjson(MOD_PATH + argv[2] + '.json')
  304.         modname = mod['name']
  305.  
  306.         if modname in data['mod']:
  307.             if mod["version"] == data["mod"][modname]["version"]:
  308.                 Alert.error("Mod '" + modname + "' version " + mod["version"] + " is already install.", data)
  309.             else:
  310.                 Alert.info("Mod '" + modname + "' version " + data["mod"][modname]["version"] + " is already install. Do you want change it for version " + mod["version"] + "?")
  311.                 choice = Alert.input("yes/no:")
  312.                 if choice == "no":
  313.                     quit()
  314.  
  315.                 uninstall(data['mod'][modname], data)
  316.  
  317.         install(mod, data)
  318.  
  319.     elif argv[1] == 'uninstall':
  320.  
  321.         if argc < 3:
  322.             Alert.error("You must give a mod name", data)
  323.  
  324.         mod = loadjson(MOD_PATH + argv[2] + '.json')
  325.         modname = mod['name']
  326.         uninstall(data['mod'][modname], data)
  327.  
  328.     elif argv[1] == 'uninstall_all':
  329.  
  330.         Alert.info("Restore all files")
  331.         for file in data['file']:
  332.             Alert.info("Restore '" + file + "'")
  333.             copyFile(BCKUP_PATH + file, file)
  334.  
  335.         data['file'] = {}
  336.         data['mod'] = {}
  337.  
  338.     elif argv[1] == 'giveall':
  339.         Alert.list([mod + " version " + data['mod'][mod]['version'] for mod in data['mod']])
  340.  
  341.     quit(data)
  342.  
  343. if __name__ == '__main__':
  344.     main(len(sys.argv), sys.argv)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top