Advertisement
JeWe37

Untitled

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