LexManos

Python MCP Obf mappings generator

Mar 21st, 2012
196
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.30 KB | None | 0 0
  1. import re, os, shutil, sys, fnmatch, csv
  2. from pprint import pprint
  3. from zipfile import ZipFile
  4. from classfile import ClassFile
  5.  
  6. base = 'C:\\Users\\Lex\\Dropbox\\Public\\MinecraftForge\\'
  7.  
  8. def main():
  9.     genMap('client.srg', 'minecraft.jar', '0')
  10.     genMap('server.srg', 'minecraft_server.jar', '1')
  11.    
  12. def genMap(srg, jar, side):
  13.     print 'Generating reflection files for %s' % ('Client' if side == '0' else 'Server')
  14.     with open(srg) as f:
  15.         srg = f.readlines()
  16.     fCsv = readCSV('fields.csv', side)
  17.     mCsv = readCSV('methods.csv', side)
  18.     data = {}
  19.     classes = {}
  20.    
  21.     for line in srg:
  22.         pts = line.split()
  23.        
  24.         if pts[0] == 'CL:':
  25.             #print ('Class %s -> %s' % (pts[1], pts[2]))
  26.             data[pts[2] + '|' + pts[1]] = {}
  27.             classes[pts[1]] = pts[2]
  28.            
  29.         elif pts[0] == 'FD:':
  30.             ps1 = pts[1].rsplit('/', 1)
  31.             ps2 = pts[2].rsplit('/', 1)
  32.             cls = ps2[0] + '|' + ps1[0]
  33.             if ps2[1] in fCsv:
  34.                 ps2[1] = fCsv[ps2[1]]
  35.             #print 'Field: %s|%s -> %s -> %s' % (ps1[0], ps2[0], ps1[1], ps2[1])
  36.             if not 'Fields' in data[cls]:
  37.                 data[cls]['Fields'] = {}
  38.             data[cls]['Fields'][ps1[1]] = ps2[1]
  39.            
  40.         elif pts[0] == 'MD:':
  41.             ps1 = pts[1].rsplit('/', 1)
  42.             ps2 = pts[3].rsplit('/', 1)
  43.             cls = ps2[0] + '|' + ps1[0]
  44.             if '/' in ps1[0]:
  45.                 pts[2] = pts[2].replace(ps1[0].rsplit('/', 1)[0] + '/', '')
  46.             if '/' in ps2[0]:
  47.                 pts[4] = pts[4].replace(ps2[0].rsplit('/', 1)[0] + '/', '')
  48.             if ps2[1] in mCsv:
  49.                 ps2[1] = mCsv[ps2[1]]
  50.             #print 'Method: %s|%s -> %s%s -> %s%s' % (ps1[0], ps2[0], ps1[1], pts[2], ps2[1], pts[4])
  51.             if not 'Methods' in data[cls]:
  52.                 data[cls]['Methods'] = {}
  53.             data[cls]['Methods'][ps1[1] + pts[2]] = ps2[1] + pts[4]
  54.            
  55.     parseJar(jar, classes, data)
  56.    
  57.     with open('%s%s_Hierarchy.txt' % (base, ('Client' if side == '0' else 'Server')), 'w') as f:        
  58.         writeHierarchy(f, makeClassHierarchy(data))
  59.            
  60.     with open('%s%s.map' % (base, ('Client' if side == '0' else 'Server')), 'w') as f:
  61.         f.write('{\n');
  62.         writeData(f, data, '    ')        
  63.         f.write('}')
  64.        
  65. def writeData(file, data, indent='', hasMore=True):
  66.     keylist = data.keys()
  67.     keylist.sort()
  68.     for x in range(0, len(keylist)):
  69.         key = keylist[x]
  70.         value = data[key]
  71.         ending = (',' if x < len(keylist) - 1 else '')
  72.         if type(value) == dict:
  73.             if len(value) == 0:
  74.                 file.write('%s"%s": {}%s\n' % (indent, key, ending))
  75.             else:
  76.                 file.write('%s"%s": {\n' % (indent, key))
  77.                 writeData(file, value, indent + '    ', x < len(keylist))
  78.                 file.write('%s}%s\n' % (indent, ending))
  79.                
  80.         elif type(value) == str or type(value) == unicode:
  81.             file.write('%s"%s": "%s"%s\n' % (indent, key, value, ending))
  82.            
  83.         elif type(value) == list:
  84.             if len(value) == 0:
  85.                 file.write('%s"%s": []%s\n' % (indent, key, ending))
  86.             elif len(value) == 1:
  87.                 file.write('%s"%s": [ "%s" ]%s\n' % (indent, key, value[0], ending))
  88.             else:
  89.                 file.write('%s"%s" : [\n' % (indent, key))
  90.                 value.sort()
  91.                 for v in range(0, len(value)):
  92.                     file.write('%s    "%s"%s\n' % (indent, value[v], (',' if v < len(value) - 1 else '')))
  93.                 file.write('%s]%s\n' % (indent, ending))
  94.         else:
  95.             print type(value)
  96.            
  97. def readCSV(filename, side):
  98.     tCsv = csv.DictReader(open(filename, 'rb'))
  99.     data = {}
  100.     for row in tCsv:
  101.         if row['side'] == side:
  102.             data[row['searge']] = row['name']
  103.     return data
  104.  
  105. def parseJar(jar, classes, data):
  106.     zip = ZipFile(jar, 'r')
  107.     for className in zip.namelist():
  108.         if className.endswith('.class'):
  109.             className = className[0:-6]
  110.             if not className in classes:
  111.                 continue
  112.                
  113.             key = classes[className] + '|' + className
  114.            
  115.             classData = zip.read(className + '.class')
  116.            
  117.             c = ClassFile(classData)            
  118.             super = str(c.super_class.get_name())
  119.            
  120.             package1 = className.rsplit('/', 1)[0] + '/'
  121.             package2 = classes[className].rsplit('/', 1)[0] + '/'
  122.            
  123.             if super != 'java/lang/Object':
  124.                 if super in classes:
  125.                     data[key]['Super'] = classes[super].replace(package2, '') + '|' + super.replace(package1, '')
  126.                 else:
  127.                     data[key]['Super'] = super
  128.                
  129.             for interface in c.interfaces:
  130.                 if not 'Interfaces' in data[key]:
  131.                     data[key]['Interfaces'] = []
  132.                 intName = str(interface.get_name())
  133.                 if intName in classes:
  134.                     data[key]['Interfaces'].append(classes[intName].replace(package2, '') + '|' + intName.replace(package1, ''))
  135.                 else:
  136.                     data[key]['Interfaces'].append(intName)
  137.        
  138.     zip.close()
  139.  
  140. def makeClassHierarchy(data):
  141.     classes = {}
  142.     classes['java/lang/Enum'] = JavaNode('java/lang/Enum')
  143.     classes['java/lang/Thread'] = JavaNode('java/lang/Thread')
  144.    
  145.     for key, value in data.items():
  146.         classes[key.split('|')[0]] = JavaNode(key.split('|')[0])
  147.        
  148.     for key, value in data.items():
  149.         cls = key.split('|')[0]
  150.         package = cls.rsplit('/', 1)[0] + '/'
  151.        
  152.         super = 'java/lang/Object'
  153.         if 'Super' in value:
  154.             super = value['Super'].split('|')[0]
  155.             if not '/' in super:
  156.                 super = package + super
  157.            
  158.         if super in classes:
  159.             classes[super].children.append(classes[cls])
  160.             classes[cls].parent = classes[super]
  161.            
  162.     for key, value in classes.items():
  163.         if not value.parent == None:
  164.             del classes[key]
  165.     return classes
  166.    
  167. def writeHierarchy(file, classes, indent='', hasMore=True):
  168.     if type(classes) == dict:
  169.         keylist = classes.keys()
  170.         keylist.sort()
  171.        
  172.         file.write('{\r\n')
  173.         for x in range(0, len(keylist)):
  174.             writeHierarchy(file, classes[keylist[x]], '    ', x < len(keylist) - 1)
  175.         file.write('}')
  176.     else:
  177.         if len(classes.children) == 0:
  178.             file.write('%s"%s": {}%s\r\n' % (indent, classes.name.replace('net/minecraft/src/', ''), (',' if hasMore else '')))
  179.         else:
  180.             file.write('%s"%s": {\r\n' % (indent, classes.name.replace('net/minecraft/src/', '')))
  181.             classes.children.sort()
  182.             for x in range(0, len(classes.children)):
  183.                 writeHierarchy(file, classes.children[x], '    ' + indent, x < len(classes.children) - 1)
  184.             file.write('%s}%s\r\n' % (indent, ',' if hasMore else ''))
  185.  
  186. class JavaNode:
  187.     def __init__(self, name):
  188.         self.name = name
  189.         self.parent = None
  190.         self.children = []
  191.        
  192. if __name__ == '__main__':
  193.     main()
Advertisement
Add Comment
Please, Sign In to add comment