Advertisement
JeWe37

Untitled

May 25th, 2017
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.94 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. import math
  10.  
  11.  
  12.  
  13. # == Command line options ==
  14.  
  15. parser = argparse.ArgumentParser(
  16.     description='Convert NBT file to Fort Sizes',
  17.     formatter_class=argparse.RawTextHelpFormatter
  18. )
  19.  
  20. parser.add_argument('files', nargs=1, metavar='FILE',
  21.                     help='Specifies file to be processed.')
  22. parser.add_argument('radius', nargs=1, metavar='RADIUS',
  23.                     help='Specifies the radius to be processed.')
  24.  
  25. args = parser.parse_args()
  26.  
  27. if len(args.files) < 1:
  28.     exit("Please specify at least one file!")
  29.  
  30.  
  31.  
  32. # == Necessary information for the parser ==
  33.  
  34. # Enum containing all known Tag-types.
  35. class Tag:
  36.     END = 0
  37.     BYTE = 1
  38.     SHORT = 2
  39.     INT = 3
  40.     LONG = 4
  41.     FLOAT = 5
  42.     DOUBLE = 6
  43.     BYTE_ARRAY = 7
  44.     STRING = 8
  45.     LIST = 9
  46.     COMPOUND = 10
  47.     INT_ARRAY = 11
  48.  
  49.  
  50. # == Generic parsing functions ==
  51.  
  52. def read_tag_start(f, assume_unnamed):
  53.     """
  54.    Parses a tag start (i.e. the beginning of a tag).
  55.    * `f` -- The file object from which the tag should be read
  56.    * `assume_unnamed` -- This flag should be set if we know that the tag which we are
  57.        about to read is unnamed (see specs for more information)
  58.    """
  59.  
  60.     tag_type = f.read(1)
  61.  
  62.     if len(tag_type) < 1:
  63.         return { 'type': Tag.END, 'name_length': 0 }
  64.     else:
  65.         tag_type = struct.unpack('>B', tag_type)[0]
  66.  
  67.     if assume_unnamed or tag_type == Tag.END:
  68.         return { 'type': tag_type, 'name_length': 0 }
  69.  
  70.     name_length = struct.unpack('>H', f.read(2))[0]
  71.     return { 'type': tag_type, 'name_length': name_length }
  72.  
  73.  
  74.  
  75. def read_tag_name(f, tag):
  76.     """
  77.    Get a tag's name from the file currently being read.
  78.    * `f` -- The file being read
  79.    * `tag` -- Tag information as extracted by `#read_tag_start
  80.    """
  81.  
  82.     if(tag['name_length'] < 1):
  83.         return ''
  84.  
  85.     return f.read(tag['name_length'])
  86.  
  87.  
  88.  
  89. # == Tag type related functions ==
  90.  
  91. # Note that these functions do not read a tag's header, but only its payload! The tag header
  92. # is read by `#read_tag_start`.
  93.  
  94.  
  95.  
  96. def read_tag_type_string(f):
  97.     """
  98.    Expected string tag format:
  99.        TAG_Short length
  100.        <"length" bytes of ASCII characters>
  101.    """
  102.     length = struct.unpack('>H', f.read(2))[0]
  103.     return f.read(length)
  104.  
  105.  
  106.  
  107. def read_tag_type_list(f):
  108.     """
  109.    Expected list tag format:
  110.        TAG_Byte tag_id
  111.        TAG_Short length
  112.        <"length" unnamed tags of type "tag_id">
  113.    """
  114.  
  115.     tag_id = tag_functions[Tag.BYTE](f)
  116.     length = tag_functions[Tag.INT](f)
  117.  
  118.     list = [ ]
  119.     for i in range(0, length):
  120.         list.append(tag_functions[tag_id](f))
  121.  
  122.     return list
  123.  
  124.  
  125.  
  126. def read_tag_type_byte_array(f):
  127.     """
  128.    Expected byte array format:
  129.        TAG_Int length
  130.        <"length" bytes>
  131.    """
  132.  
  133.     length = tag_functions[Tag.INT](f)
  134.  
  135.     list = [ ]
  136.     for i in range(0, length):
  137.         list.append(tag_functions[Tag.BYTE](f))
  138.  
  139.     return list
  140.  
  141. def read_tag_type_int_array(f):
  142.     """
  143.    Expected int array format:
  144.        TAG_Int length
  145.        <"length" bytes>
  146.    """
  147.  
  148.     length = tag_functions[Tag.INT](f)
  149.  
  150.     list = [ ]
  151.     for i in range(0, length):
  152.         list.append(tag_functions[Tag.INT](f))
  153.  
  154.     return list
  155.  
  156.  
  157.  
  158. def read_tag_type_compound(f, assume_unnamed=False):
  159.     """
  160.    Expected compound tag format: a number of named tags until a Tag_END is found, i.e.:
  161.        <named_tag_1..named_tag_N>
  162.        TAG_end
  163.    """
  164.  
  165.     current = { }
  166.  
  167.     while(True):
  168.         tag = read_tag_start(f, assume_unnamed)
  169.         name = read_tag_name(f, tag)
  170.  
  171.         if tag['type'] == Tag.COMPOUND:
  172.             current[name] = tag_functions[tag['type']](f)
  173.         elif tag['type'] == Tag.END:
  174.             break
  175.         else:
  176.             current[name] = tag_functions[tag['type']](f)
  177.  
  178.     return current
  179.  
  180. # def section(h, r=1):
  181. #     return math.sqrt(r*r-h*h) if h < r else 0
  182. #
  183. # def g(x, h, r=1):
  184. #     x = float(x)
  185. #     return 0.5*(math.sqrt(1-x*x/(r*r))*x*r+r*r*math.asin(x/r)-2*h*x)
  186. #
  187. # def area(*args):
  188. #     x0 = args[0]
  189. #     x1 = args[1]
  190. #     if len(args) == 4:
  191. #         h = args[2]
  192. #         r = args[3]
  193. #         if x0 > x1:
  194. #             x0,x1 = x1,x0
  195. #         s = section(h, r)
  196. #         return g(max(-s, min(s, x1)), h, r)-g(max(-s,min(s,x0)),h,r)
  197. #     elif len(args) == 5:
  198. #         y0 = args[2]
  199. #         y1 = args[3]
  200. #         r = args[4]
  201. #         if y0 > y1:
  202. #             y0,y1 = y1,y0
  203. #         if y0 < 0:
  204. #             if y1 < 0:
  205. #                 return area(x0, x1, -y0, -y1, r)
  206. #             else:
  207. #                 return area(x0, x1, 0, -y0, r)+area(x0, x1, 0, y1, r)
  208. #         else:
  209. #             return area(x0, x1, y0, r)-area(x0, x1, y1, r)
  210. #     elif len(args) == 7:
  211. #         y0 = args[2]-args[5]
  212. #         y1 = args[3]-args[5]
  213. #         x0 -= args[4]
  214. #         x1 -= args[4]
  215. #         r = args[6]
  216. #         return area(x0, x1, y0, y1, r)
  217.  
  218.  
  219. def RectIntersect(a, b):  # returns None if rectangles don't intersect RECT: [x0, x1, z0, z1]
  220.     Rect = [max(a[0],b[0]), min(a[1],b[1]), max(a[2],b[2]), min(a[3],b[3])]
  221.     return Rect if Rect[0] < Rect[1] and Rect[2] < Rect[3] else None
  222.  
  223. def RectArea(Rect):
  224.     return (Rect[1]-Rect[0])*(Rect[3]-Rect[2]) if Rect is not None else 0
  225.  
  226. # === Tag functions object ===
  227.  
  228. # This object contains functions to parse all known tag types, accessible by `tag id`.
  229. # If you're not familiar with this idiom: it is used in a similar fashion to `switch`-statements
  230. # in other languages ([Stackoverflow](http://stackoverflow.com/questions/374239/why-doesnt-python-have-a-switch-statement))
  231.  
  232. tag_functions = {
  233.     Tag.END: lambda f: struct.unpack('>B', f.read(1))[0],
  234.     Tag.BYTE: lambda f: struct.unpack('>B', f.read(1))[0],
  235.     Tag.SHORT: lambda f: struct.unpack('>h', f.read(2))[0],
  236.     Tag.INT: lambda f: struct.unpack('>i', f.read(4))[0],
  237.     Tag.LONG: lambda f: struct.unpack('>q', f.read(8))[0],
  238.     Tag.FLOAT: lambda f: struct.unpack('>f', f.read(4))[0],
  239.     Tag.DOUBLE: lambda f: struct.unpack('>d', f.read(8))[0],
  240.     Tag.BYTE_ARRAY: read_tag_type_byte_array,
  241.     Tag.STRING: read_tag_type_string,
  242.     Tag.LIST: read_tag_type_list,
  243.     Tag.COMPOUND: read_tag_type_compound,
  244.     Tag.INT_ARRAY: read_tag_type_int_array
  245. }
  246.  
  247.  
  248. # ---
  249.  
  250. # ==== Invoke the parser ====
  251.  
  252. #f = gzip.GzipFile(os.path.join(args.files[0], "data/Fortress.dat"), 'rb')
  253. f = gzip.GzipFile(os.path.join(args.files[0], "data/Fortress.dat"), 'rb')
  254. x1 = tag_functions[Tag.COMPOUND](f)
  255.  
  256.  
  257.  
  258. #maximum = max((Fort["BB"][3]-Fort["BB"][0])*(Fort["BB"][5]-Fort["BB"][2]) for Fort in x[""]["data"]["Features"].values())
  259. #
  260. #for Fort in x[""]["data"]["Features"].values():
  261. # if (Fort["BB"][3]-Fort["BB"][0])*(Fort["BB"][5]-Fort["BB"][2]) == maximum:
  262. #     print(str(Fort["ChunkX"]) + "/" + str(Fort["ChunkZ"]) + ": " + str((Fort["BB"][3]-Fort["BB"][0])*(Fort["BB"][5]-Fort["BB"][2])))
  263.  
  264. # maximum = 0
  265. Intersections = []
  266. Fortresses = []
  267.  
  268. for Fortress in x1[""]["data"]["Features"].values():
  269.     Fortresses.append([Fortress["BB"][0], Fortress["BB"][3], Fortress["BB"][2], Fortress["BB"][5]])
  270.    
  271. for Fort0 in Fortresses:
  272.     for Fort1 in Fortresses:
  273.         Intersect = RectIntersect([Fort0[0], Fort0[1], Fort0[2], Fort0[3]], [Fort1[0], Fort1[1], Fort1[2], Fort1[3]])
  274.         if Intersect and Intersect not in Intersections and Intersect not in Fortresses:
  275.             Intersections.append(Intersect)
  276.  
  277. radius = int(args.radius[0])
  278.  
  279. # for x in range(-radius, radius):
  280. #     for y in range(-radius, radius):
  281. #         score = 0
  282. #         for Fort in Fortresses:
  283. #             score += area(Fort[0], Fort[1], Fort[2], Fort[3], x*5, y*5, 128)-area(Fort[0], Fort[1], Fort[2], Fort[3], x*5, y*5, 70)
  284. #         for Intersection in Intersections:
  285. #             score += area(Intersection[0], Intersection[1], Intersection[2], Intersection[3], x*5, y*5, 70)-area(Intersection[0], Intersection[1], Intersection[2], Intersection[3], x*5, y*5, 128)
  286. #         if score > maximum*0.875:
  287. #             for x1 in range(x*5-5, x*5+5):
  288. #                 for y1 in range(y*5-5, y*5+5):
  289. #                     score = 0
  290. #                     for Fort in Fortresses:
  291. #                         score += area(Fort[0], Fort[1], Fort[2], Fort[3], x1, y1, 128)-area(Fort[0], Fort[1], Fort[2], Fort[3], x1, y1, 70)
  292. #                     for Intersection in Intersections:
  293. #                         score += area(Intersection[0], Intersection[1], Intersection[2], Intersection[3], x1, y1, 70)-area(Intersection[0], Intersection[1], Intersection[2], Intersection[3], x1, y1, 128)
  294. #                     if score > maximum:
  295. #                         maximum = score
  296. #                         print(str(x1) + "/" + str(y1) + ": " + str(score))
  297.  
  298. for x in range(-radius, radius):
  299.     for y in range(-radius, radius):
  300.         Rects = (
  301.             [x-127, x-87, y-18, y+18],
  302.             [x+87, x+127, y-18, y+18],
  303.             [x-18, x+18, y-127, y-87],
  304.             [x-18, x+18, y+87, y+127]
  305.         )
  306.         for Rect in Rects:
  307.             Filled = 0
  308.             for Fort in Fortresses:
  309.                 Filled += RectArea(RectIntersect(Rect, Fort))
  310.             for Intersection in Intersections:
  311.                 Filled -= RectArea(RectIntersect(Rect, Intersection))
  312.             if Filled != 1440:
  313.                 break
  314.         else:
  315.             print("Candidate: " + str(x) + "/" + str(y))
  316.  
  317.  
  318. #off are 1;2;3;5;6;7
  319.  
  320. #print(area(-13, 195, -6, 176, 109, 82, 128))
  321.  
  322. #x = 109
  323. #y = 82
  324. #score = 0
  325. #for Fort in Fortresses:
  326. #    if area(Fort[0], Fort[1], Fort[2], Fort[3], x, y, 128)-area(Fort[0], Fort[1], Fort[2], Fort[3], x, y, 70) != 0:
  327. #        print str(Fort) + " " + str(area(Fort[0], Fort[1], Fort[2], Fort[3], x, y, 128)-area(Fort[0], Fort[1], Fort[2], Fort[3], x, y, 70))
  328. #    score += area(Fort[0], Fort[1], Fort[2], Fort[3], x, y, 128)-area(Fort[0], Fort[1], Fort[2], Fort[3], x, y, 70)
  329. #for Intersection in Intersections:
  330. #    score += area(Intersection[0], Intersection[1], Intersection[2], Intersection[3], x, y, 70)-area(Intersection[0], Intersection[1], Intersection[2], Intersection[3], x, y, 128)
  331. #if score > maximum:
  332. #    maximum = score
  333. #    print(str(x) + "/" + str(y) + ": " + str(score))
  334.  
  335. #print(RectIntersect([-2, -1, -2, -1], [-3, -1.5, -3, -1.5]))
  336.  
  337. # print(area(-10, 10, -10, 10, 0, 0, 1)) # unit circle completely inside a huge box, area of intersection is pi
  338. # print(area(-10, 0, -10, 10, 0, 0, 1)) # half of unit circle inside a large box, area of intersection is pi/2
  339. # print(area(0, 10, -10, 10, 0, 0, 1)) # half of unit circle inside a large box, area of intersection is pi/2
  340. # print(area(-10, 10, -10, 0, 0, 0, 1)) # half of unit circle inside a large box, area of intersection is pi/2
  341. # print(area(-10, 10, 0, 10, 0, 0, 1)) # half of unit circle inside a large box, area of intersection is pi/2
  342. # print(area(0, 1, 0, 1, 0, 0, 1)) # unit box covering one quadrant of the circle, area of intersection is pi/4
  343. # print(area(0, -1, 0, 1, 0, 0, 1)) # unit box covering one quadrant of the circle, area of intersection is pi/4
  344. # print(area(0, -1, 0, -1, 0, 0, 1)) # unit box covering one quadrant of the circle, area of intersection is pi/4
  345. # print(area(0, 1, 0, -1, 0, 0, 1)) # unit box covering one quadrant of the circle, area of intersection is pi/4
  346. # print(area(-.5, .5, -.5, .5, 0, 0, 10)) # unit box completely inside a huge circle, area of intersection is 1
  347. # print(area(-20, -10, -10, 10, 0, 0, 1)) # huge box completely outside a circle (left), area of intersection is 0
  348. # print(area(10, 20, -10, 10, 0, 0, 1)) # huge box completely outside a circle (right), area of intersection is 0
  349. # print(area(-10, 10, -20, -10, 0, 0, 1)) # huge box completely outside a circle (below), area of intersection is 0
  350. # print(area(-10, 10, 10, 20, 0, 0, 1)) # huge box completely outside a circle (above), area of intersection is 0
  351.  
  352.  
  353. # ==== Print the resulting JSON-string to stdout ====
  354. #print json.JSONEncoder().encode(x)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement