Advertisement
JeWe37

Untitled

May 13th, 2017
372
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.42 KB | None | 0 0
  1. #python2 nbt.py "/home/jewe37/.minecraft/saves/JeWe37 - 20 - Kopie/"
  2.  
  3.  
  4. import argparse
  5. import struct
  6. import gzip
  7. import os
  8. import json
  9.  
  10.  
  11.  
  12. # == Command line options ==
  13.  
  14. parser = argparse.ArgumentParser(
  15.     description='Convert NBT file to Fort Sizes',
  16.     formatter_class=argparse.RawTextHelpFormatter
  17. )
  18.  
  19. parser.add_argument('files', nargs=1, metavar='FILE',
  20.                     help='Specifies file to be processed.')
  21.  
  22. args = parser.parse_args()
  23.  
  24. if len(args.files) < 1:
  25.     exit("Please specify at least one file!")
  26.  
  27.  
  28.  
  29. # == Necessary information for the parser ==
  30.  
  31. # Enum containing all known Tag-types.
  32. class Tag:
  33.     END = 0
  34.     BYTE = 1
  35.     SHORT = 2
  36.     INT = 3
  37.     LONG = 4
  38.     FLOAT = 5
  39.     DOUBLE = 6
  40.     BYTE_ARRAY = 7
  41.     STRING = 8
  42.     LIST = 9
  43.     COMPOUND = 10
  44.     INT_ARRAY = 11
  45.  
  46.  
  47. # == Generic parsing functions ==
  48.  
  49. def read_tag_start(f, assume_unnamed):
  50.     """
  51.    Parses a tag start (i.e. the beginning of a tag).
  52.    * `f` -- The file object from which the tag should be read
  53.    * `assume_unnamed` -- This flag should be set if we know that the tag which we are
  54.        about to read is unnamed (see specs for more information)
  55.    """
  56.  
  57.     tag_type = f.read(1)
  58.  
  59.     if len(tag_type) < 1:
  60.         return { 'type': Tag.END, 'name_length': 0 }
  61.     else:
  62.         tag_type = struct.unpack('>B', tag_type)[0]
  63.  
  64.     if assume_unnamed or tag_type == Tag.END:
  65.         return { 'type': tag_type, 'name_length': 0 }
  66.  
  67.     name_length = struct.unpack('>H', f.read(2))[0]
  68.     return { 'type': tag_type, 'name_length': name_length }
  69.  
  70.  
  71.  
  72. def read_tag_name(f, tag):
  73.     """
  74.    Get a tag's name from the file currently being read.
  75.    * `f` -- The file being read
  76.    * `tag` -- Tag information as extracted by `#read_tag_start
  77.    """
  78.  
  79.     if(tag['name_length'] < 1):
  80.         return ''
  81.  
  82.     return f.read(tag['name_length'])
  83.  
  84.  
  85.  
  86. # == Tag type related functions ==
  87.  
  88. # Note that these functions do not read a tag's header, but only its payload! The tag header
  89. # is read by `#read_tag_start`.
  90.  
  91.  
  92.  
  93. def read_tag_type_string(f):
  94.     """
  95.    Expected string tag format:
  96.        TAG_Short length
  97.        <"length" bytes of ASCII characters>
  98.    """
  99.     length = struct.unpack('>H', f.read(2))[0]
  100.     return f.read(length)
  101.  
  102.  
  103.  
  104. def read_tag_type_list(f):
  105.     """
  106.    Expected list tag format:
  107.        TAG_Byte tag_id
  108.        TAG_Short length
  109.        <"length" unnamed tags of type "tag_id">
  110.    """
  111.  
  112.     tag_id = tag_functions[Tag.BYTE](f)
  113.     length = tag_functions[Tag.INT](f)
  114.  
  115.     list = [ ]
  116.     for i in range(0, length):
  117.         list.append(tag_functions[tag_id](f))
  118.  
  119.     return list
  120.  
  121.  
  122.  
  123. def read_tag_type_byte_array(f):
  124.     """
  125.    Expected byte array format:
  126.        TAG_Int length
  127.        <"length" bytes>
  128.    """
  129.  
  130.     length = tag_functions[Tag.INT](f)
  131.  
  132.     list = [ ]
  133.     for i in range(0, length):
  134.         list.append(tag_functions[Tag.BYTE](f))
  135.  
  136.     return list
  137.  
  138. def read_tag_type_int_array(f):
  139.     """
  140.    Expected int array format:
  141.        TAG_Int length
  142.        <"length" bytes>
  143.    """
  144.  
  145.     length = tag_functions[Tag.INT](f)
  146.  
  147.     list = [ ]
  148.     for i in range(0, length):
  149.         list.append(tag_functions[Tag.INT](f))
  150.  
  151.     return list
  152.  
  153.  
  154.  
  155. def read_tag_type_compound(f, assume_unnamed=False):
  156.     """
  157.    Expected compound tag format: a number of named tags until a Tag_END is found, i.e.:
  158.        <named_tag_1..named_tag_N>
  159.        TAG_end
  160.    """
  161.  
  162.     current = { }
  163.  
  164.     while(True):
  165.         tag = read_tag_start(f, assume_unnamed)
  166.         name = read_tag_name(f, tag)
  167.  
  168.         if tag['type'] == Tag.COMPOUND:
  169.             current[name] = tag_functions[tag['type']](f)
  170.         elif tag['type'] == Tag.END:
  171.             break
  172.         else:
  173.             current[name] = tag_functions[tag['type']](f)
  174.  
  175.     return current
  176.  
  177.  
  178. # === Tag functions object ===
  179.  
  180. # This object contains functions to parse all known tag types, accessible by `tag id`.
  181. # If you're not familiar with this idiom: it is used in a similar fashion to `switch`-statements
  182. # in other languages ([Stackoverflow](http://stackoverflow.com/questions/374239/why-doesnt-python-have-a-switch-statement))
  183.  
  184. tag_functions = {
  185.     Tag.END: lambda f: struct.unpack('>B', f.read(1))[0],
  186.     Tag.BYTE: lambda f: struct.unpack('>B', f.read(1))[0],
  187.     Tag.SHORT: lambda f: struct.unpack('>h', f.read(2))[0],
  188.     Tag.INT: lambda f: struct.unpack('>i', f.read(4))[0],
  189.     Tag.LONG: lambda f: struct.unpack('>q', f.read(8))[0],
  190.     Tag.FLOAT: lambda f: struct.unpack('>f', f.read(4))[0],
  191.     Tag.DOUBLE: lambda f: struct.unpack('>d', f.read(8))[0],
  192.     Tag.BYTE_ARRAY: read_tag_type_byte_array,
  193.     Tag.STRING: read_tag_type_string,
  194.     Tag.LIST: read_tag_type_list,
  195.     Tag.COMPOUND: read_tag_type_compound,
  196.     Tag.INT_ARRAY: read_tag_type_int_array
  197. }
  198.  
  199.  
  200. # ---
  201.  
  202. # ==== Invoke the parser ====
  203.  
  204. f = gzip.GzipFile(os.path.join(args.files[0], "data/Fortress.dat"), 'rb')
  205. x = tag_functions[Tag.COMPOUND](f)
  206.  
  207. maximum = max((Fort["BB"][3]-Fort["BB"][0])*(Fort["BB"][5]-Fort["BB"][2]) for Fort in x[""]["data"]["Features"].values())
  208.  
  209. for Fort in x[""]["data"]["Features"].values():
  210.     if (Fort["BB"][3]-Fort["BB"][0])*(Fort["BB"][5]-Fort["BB"][2]) == maximum:
  211.         print(str(Fort["ChunkX"]) + "/" + str(Fort["ChunkZ"]) + ": " + str((Fort["BB"][3]-Fort["BB"][0])*(Fort["BB"][5]-Fort["BB"][2])))
  212.  
  213.  
  214.  
  215. # ==== Print the resulting JSON-string to stdout ====
  216. #print json.JSONEncoder().encode(x)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement