|
| 1 | +import zlib, sys, pprint |
| 2 | +from sc2reader.utils import ReplayBuffer |
| 3 | +from sc2reader.data.build19595 import Data_19595 as DataObject |
| 4 | + |
| 5 | +unitData = DataObject() |
| 6 | + |
| 7 | +races = {'Prot':'Protoss','Zerg':'Zerg','Terr':'Terran','RAND':'Random'} |
| 8 | +data_names = [ |
| 9 | + 'R', |
| 10 | + 'U', |
| 11 | + 'S', |
| 12 | + 'O', |
| 13 | + 'AUR', |
| 14 | + 'RCR', |
| 15 | + 'WC', |
| 16 | + 'UT', |
| 17 | + 'KUC', |
| 18 | + 'SB', |
| 19 | + 'SRC', |
| 20 | + |
| 21 | +] |
| 22 | +data_names_pretty = [ |
| 23 | + 'Resources', |
| 24 | + 'Units', |
| 25 | + 'Structures', |
| 26 | + 'Overview', |
| 27 | + 'Average Unspent Resources', |
| 28 | + 'Resource Collection Rate', |
| 29 | + 'Workers Created', |
| 30 | + 'Units Trained', |
| 31 | + 'Killed Unit Count', |
| 32 | + 'Structures Built', |
| 33 | + 'Structures Razed Count' |
| 34 | +] |
| 35 | + |
| 36 | +def getRealm(str): |
| 37 | + if str == '\x00\x00S2': |
| 38 | + return "EU" |
| 39 | + |
| 40 | + return "?" |
| 41 | +def getPlayers(data): |
| 42 | + players = [] |
| 43 | + parr = data[0][3] |
| 44 | + for i in range(16): |
| 45 | + if not (parr[i][0][1] == 0): |
| 46 | + players.append(getPlayer(data, i)) |
| 47 | + |
| 48 | + return players |
| 49 | +def getIncomeGraph(data, index): |
| 50 | + return getGraph(data[4][0][1][1], index) |
| 51 | +def getArmyGraph(data, index): |
| 52 | + return getGraph(data[4][0][2][1], index) |
| 53 | +def getGraph(graph, index): |
| 54 | + return [(o[2], o[0]) for o in graph[index]] |
| 55 | +def getPlayer(data, index): |
| 56 | + pinfo = data[0][3][index] |
| 57 | + pdata = data[3][0] |
| 58 | + |
| 59 | + player = { |
| 60 | + 'id': "{}/{}/{}".format(getRealm(pinfo[0][1][0][1]), pinfo[0][1][0][2], pinfo[0][1][0][3]), |
| 61 | + 'race' : races[pinfo[2]] |
| 62 | + } |
| 63 | + |
| 64 | + stats = {} |
| 65 | + |
| 66 | + for i in range(len(pdata)): |
| 67 | + stats[data_names[i]] = pdata[i][1][index][0][0] |
| 68 | + stats[data_names[len(pdata)]] = data[4][0][0][1][index][0][0] |
| 69 | + player['stats'] = stats |
| 70 | + player['graphs'] = {} |
| 71 | + player['graphs']['income'] = getIncomeGraph(data, index) |
| 72 | + player['graphs']['army'] = getArmyGraph(data, index) |
| 73 | + |
| 74 | + return player |
| 75 | +def flip_int(num, b): |
| 76 | + """ |
| 77 | + Flips the b first bytes in num |
| 78 | + Example: |
| 79 | + (0x12345, 3) -> 0x452301 |
| 80 | + (0x00112233, 4) -> 0x33221100 |
| 81 | + """ |
| 82 | + o = 0 |
| 83 | + for i in range(b/2): |
| 84 | + o |= ((num & (0xff << i*8)) << (b-(2*i+1))*8) |
| 85 | + o |= ((num & (0xff << (b-(i+1))*8)) >> (b-(2*i+1)) * 8) |
| 86 | + if b % 2 == 1: |
| 87 | + o |= (num & (0xff << (b/2)*8)) |
| 88 | + return o |
| 89 | + |
| 90 | +def toTime(bo_time): |
| 91 | + return (bo_time >> 8) / 16 |
| 92 | +def toUnit(bo_unit): |
| 93 | + #print(hex(flip_int(bo_unit, 4))) |
| 94 | + i = ((bo_unit & 0xff) << 8) | 0x01 |
| 95 | + if bo_unit >> 24 == 1: |
| 96 | + return {'name':unitData.type(i).name, 'id':hex(i)} |
| 97 | + return None |
| 98 | +def getBuildOrder(unit_structs, index): |
| 99 | + ''' [ {supply, time, unit} ] ''' |
| 100 | + bo = [] |
| 101 | + for unit_struct in unit_structs: |
| 102 | + for u in unit_struct: |
| 103 | + unit = toUnit(u[0][1]) |
| 104 | + if not unit: |
| 105 | + continue |
| 106 | + for entry in u[1][index]: |
| 107 | + bo.append({ |
| 108 | + 'supply' : entry[0], |
| 109 | + 'total_supply' : entry[1]&0xff, |
| 110 | + 'time' : toTime(entry[2]), |
| 111 | + 'time_hex' : hex(entry[2]>>8), |
| 112 | + 'unit' : unit, |
| 113 | + 'build_index' : entry[1] >> 16, |
| 114 | + 'struct_as_hex' : {0:hex(entry[0]), |
| 115 | + 1:hex(entry[1]), |
| 116 | + 2:hex(entry[2]), |
| 117 | + } |
| 118 | + }) |
| 119 | + bo.sort(key=lambda x: x['build_index']) |
| 120 | + return bo |
| 121 | + |
| 122 | +def getBuildOrders(data): |
| 123 | + unit_structs = [x[0] for x in data[5:]] |
| 124 | + players = {} |
| 125 | + for i in range(15): |
| 126 | + bo = getBuildOrder(unit_structs, i) |
| 127 | + if len(bo) > 0: |
| 128 | + players[i] = bo |
| 129 | + all = [u for p in players for u in players[p]] |
| 130 | + all.sort(key=lambda x: x['build_index']) |
| 131 | + return [players, all] |
| 132 | + |
| 133 | +def main(): |
| 134 | + arg = sys.argv[2] if len(sys.argv) >= 3 else "pprint" |
| 135 | + with open(sys.argv[1],"rb") as s2gs: |
| 136 | + raw_data = zlib.decompress(s2gs.read()[16:]) |
| 137 | + data = list() |
| 138 | + buffer = ReplayBuffer(raw_data) |
| 139 | + while buffer.left: |
| 140 | + part = buffer.read_data_struct() |
| 141 | + data.append(part) |
| 142 | + |
| 143 | + if arg == "players": |
| 144 | + pprint.PrettyPrinter(indent=2).pprint(getPlayers(data)) |
| 145 | + elif arg == "pprint": |
| 146 | + pprint.PrettyPrinter(indent=2).pprint(data) |
| 147 | + elif arg == "bo": |
| 148 | + pprint.PrettyPrinter(indent=2).pprint(getBuildOrders(data)) |
| 149 | + |
| 150 | +main() |
0 commit comments