diff --git a/dist/index.d.mts b/dist/index.d.mts index 0cca704..87f780c 100644 --- a/dist/index.d.mts +++ b/dist/index.d.mts @@ -75,4 +75,4 @@ declare function parseReplay(fileArrayBuffer: ArrayBuffer): Replay; declare function parseTeam(dataView: DataView, uint8Ary: Uint8Array): Team[]; -export { parseChat, parseDeck, parseField, parseReplay, parseTeam }; +export { type Deck, type GameSetting, type Message, type Player, type Replay, type Team, parseChat, parseDeck, parseField, parseReplay, parseTeam }; diff --git a/dist/index.d.ts b/dist/index.d.ts index 0cca704..87f780c 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -75,4 +75,4 @@ declare function parseReplay(fileArrayBuffer: ArrayBuffer): Replay; declare function parseTeam(dataView: DataView, uint8Ary: Uint8Array): Team[]; -export { parseChat, parseDeck, parseField, parseReplay, parseTeam }; +export { type Deck, type GameSetting, type Message, type Player, type Replay, type Team, parseChat, parseDeck, parseField, parseReplay, parseTeam }; diff --git a/dist/index.js.map b/dist/index.js.map index 2dc95df..7fda8e1 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/index.ts","../src/parseChat.ts","../src/constant.ts","../src/util.ts","../src/parseDeck.ts","../src/parseField.ts","../src/parseReplay.ts","../src/parseTeam.ts"],"sourcesContent":["import { parseChat } from \"./parseChat\";\nimport { parseDeck } from \"./parseDeck\";\nimport { parseField } from \"./parseField\";\nimport { parseReplay } from \"./parseReplay\";\nimport { parseTeam } from \"./parseTeam\";\n\nexport { parseChat, parseDeck, parseField, parseReplay, parseTeam }","import { inflateRaw } from \"pako\";\nimport { Message } from \"./dataStructures\";\nimport { readInt32, readInt8, readString, search } from \"./util\";\nimport { headerLength } from \"./constant\";\n\nexport function parseChat(fileArrayBuffer: ArrayBuffer): Message[] {\n let uint8Ary: Uint8Array = inflateRaw(fileArrayBuffer.slice(headerLength));\n let dataView: DataView = new DataView(uint8Ary.buffer);\n let chat: Message[] = [];\n let searchBytes = [0x9a, 0x99, 0x99, 0x3d];\n let position = search(uint8Ary, searchBytes) + 142;\n const msgLen = readInt32(dataView, position);\n position += 4;\n // starting messages\n for (let i = 0; i < msgLen; i++) {\n let from = readInt32(dataView, position); // from\n position += 4;\n let to = readInt32(dataView, position); // to\n position += 4;\n const bufLen = readInt32(dataView, position);\n position += 4;\n let msg = readString(dataView, position, bufLen);\n position += bufLen * 2;\n position += 1;\n chat.push({\n fromId: from,\n toId: to,\n message: msg,\n time: 0,\n });\n }\n\n let duration: number = 0;\n searchBytes = [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x19];\n while (true) {\n position = search(uint8Ary, searchBytes, position);\n if (position == -1) break;\n position += 113;\n const command = readInt8(dataView, position);\n position += 1;\n switch (command) {\n case 33:\n case 65:\n case 161:\n case 193:\n break;\n case 1:\n case 129:\n break;\n case 35:\n case 37:\n case 41:\n case 67:\n case 73:\n case 163:\n case 165:\n case 169:\n case 195:\n case 201:\n position += 4;\n break;\n case 3:\n case 5:\n case 9:\n case 131:\n case 133:\n case 137:\n position += 4;\n break;\n case 39:\n case 43:\n case 45:\n case 75:\n case 167:\n case 171:\n case 173:\n case 203:\n position += 8;\n break;\n case 7:\n case 11:\n case 13:\n case 135:\n case 139:\n case 141:\n position += 8;\n break;\n case 47:\n case 175:\n case 207:\n position += 12;\n break;\n case 15:\n case 143:\n position += 12;\n break;\n case 49:\n case 177:\n position += 36;\n break;\n case 17:\n case 145:\n position += 36;\n break;\n case 19:\n case 21:\n case 25:\n case 147:\n case 149:\n case 153:\n position += 40;\n break;\n case 51:\n case 53:\n case 57:\n case 179:\n case 181:\n case 185:\n position += 40;\n break;\n case 55:\n case 59:\n case 61:\n case 183:\n case 187:\n case 189:\n position += 44;\n break;\n case 23:\n case 27:\n case 29:\n case 151:\n case 155:\n case 157:\n position += 44;\n break;\n case 63:\n case 191:\n case 223:\n position += 48;\n break;\n case 31:\n case 159:\n position += 48;\n break;\n default:\n console.error(`Unknown main command: ${command}`);\n position = search(uint8Ary, searchBytes, position)\n continue\n }\n\n const messageCount = readInt32(dataView, position);\n position += 4;\n\n for (let i = 0; i < messageCount; i++) {\n const from = readInt32(dataView, position);\n position += 4;\n const to = readInt32(dataView, position);\n position += 4;\n let bufLen = readInt32(dataView, position);\n position += 4;\n const msg = readString(dataView, position, bufLen);\n position += bufLen * 2;\n position += 1;\n chat.push({\n fromId: from,\n toId: to,\n message: msg,\n time: duration,\n });\n }\n\n duration += readInt8(dataView, position);\n position += 1;\n }\n return chat;\n}","export const headerLength: number = 10;\nexport const decoder = new TextDecoder('utf-16');\nexport const englishRegex: RegExp = /^[A-Za-z0-9_]*$/;","import { decoder } from \"./constant\";\n\nexport function readString(dataView: DataView, position: number, length: number): string {\n const end = position + length * 2;\n const string = decoder.decode(dataView.buffer.slice(position, end));\n return string\n}\n\nexport function readInt32(dataView: DataView, position: number): number {\n const int32 = dataView.getInt32(position, true);\n return int32\n}\n\nexport function readFloat32(dataView: DataView, position: number): number {\n const float32 = dataView.getFloat32(position, true)\n return float32;\n}\n\nexport function readBool(dataView: DataView, position: number): boolean {\n const bool = dataView.getUint8(position);\n return Boolean(bool);\n}\n\nexport function readInt8(dataView: DataView, position: number): number {\n const int8 = dataView.getUint8(position)\n return int8\n}\n\nexport function searchDeck(dataView: DataView, uint8Ary: Uint8Array, startIndex: number): number {\n let position = startIndex;\n while (position < uint8Ary.length) {\n position = search(uint8Ary, [0x0, 0x0, 0x0, 0x44, 0x6b], position);\n if (position == -1) break;\n position += 9;\n let int = readInt32(dataView, position);\n if (int != 5) continue;\n return position - 4;\n }\n return -1;\n}\n\nexport function search(array: Uint8Array, search: number[], fromIndex: number = 0): number {\n const searchLen = search.length\n const searchLast = search[searchLen - 1]\n let index = array.indexOf(searchLast, fromIndex + searchLen - 1)\n\n while (index !== -1) {\n for (let i = searchLen - 1; i > 0; i--) {\n if (search[i - 1] !== array[index - searchLen + i]) {\n const searchIndex = search.lastIndexOf(array[index + 1])\n const offset = searchIndex === -1 ? index + searchLen + 1 : index + searchLen - searchIndex\n index = array.indexOf(searchLast, offset)\n break;\n }\n if (i === 1) return index - searchLen + 1\n }\n }\n return -1\n}","import { Deck } from \"./dataStructures\";\nimport { readInt32, searchDeck, readString, readBool } from \"./util\";\n\nexport function parseDeck(dataView: DataView, uint8Ary: Uint8Array): Deck[] {\n let decks: Deck[] = [];\n let position = 0;\n while (true) {\n let currentDeckPosition: number = position;\n let nextDeckOffset: number = readInt32(dataView, position);\n position += 4;\n let check: number = readInt32(dataView, position);\n position += 4;\n if (check != 5) {\n // if check isn't 5, it's not a deck\n position = searchDeck(dataView, uint8Ary, position);\n if (position == -1) break;\n continue;\n }\n let deckId: number = readInt32(dataView, position);\n position += 4;\n let stringLength: number = readInt32(dataView, position);\n position += 4;\n let deckName: string = readString(dataView, position, stringLength);\n position += stringLength * 2;\n var gameId = readInt32(dataView, position);\n position += 4;\n var isDefault = readBool(dataView, position);\n position += 1;\n let unKnownBool = readBool(dataView, position);\n position += 1;\n var cardCount = readInt32(dataView, position);\n position += 4;\n let techIds: number[] = [];\n for (let j = 0; j < cardCount; j++) {\n let techId = readInt32(dataView, position);\n techIds.push(techId);\n position += 4;\n }\n\n let deck: Deck = {\n deckName: deckName,\n deckId: deckId,\n gameId: gameId,\n isDefault: isDefault,\n cardCount: cardCount,\n techIds: techIds,\n };\n decks.push(deck);\n position = currentDeckPosition + nextDeckOffset + 6;\n }\n return decks;\n}","import { englishRegex } from \"./constant\";\nimport { readString, readInt32, readFloat32, readBool } from \"./util\";\n\nexport function parseField(dataView: DataView): { [k: string]: any } {\n let dictionary: { [k: string]: any } = {};\n let position = 0;\n let endPosition = 20000; // the position of the fields won't exceed this number\n let skipCount: number = 0;\n while (position < endPosition) {\n let word = readString(dataView, position, 1);\n if (englishRegex.test(word)) {\n if (skipCount >= 4) {\n let isNextWord = true;\n let nextWordLength: number = readInt32(dataView, position - 4);\n let nextWord = readString(dataView, position, nextWordLength);\n for (let char of nextWord) {\n if (!englishRegex.test(char)) {\n isNextWord = false;\n break;\n }\n }\n if (isNextWord) {\n position += nextWord.length * 2;\n let dataType = readInt32(dataView, position);\n position += 4;\n let data: any;\n switch (dataType) {\n case 1:\n data = readFloat32(dataView, position);\n position += 4;\n dictionary[nextWord] = data;\n break;\n case 2:\n data = readInt32(dataView, position);\n position += 4;\n dictionary[nextWord] = data;\n break;\n case 5:\n let bool = readBool(dataView, position);\n position += 1;\n dictionary[nextWord] = bool;\n break;\n case 9:\n let stringLength = readInt32(dataView, position);\n if (stringLength > 100) {\n position -= 4;\n // if stringLength is very long, it's most likely not a field.\n break;\n }\n position += 4;\n let string = readString(dataView, position, stringLength);\n position += stringLength * 2;\n dictionary[nextWord] = string;\n break;\n }\n } else {\n position += 2;\n }\n skipCount = 0;\n } else {\n position += 2;\n }\n } else {\n position += 1;\n skipCount += 1;\n }\n }\n return dictionary;\n}","import { inflateRaw } from \"pako\";\nimport { headerLength } from \"./constant\";\nimport { Replay, GameSetting, Player, Deck, Team } from \"./dataStructures\";\nimport { parseDeck } from \"./parseDeck\";\nimport { parseField } from \"./parseField\";\nimport { parseTeam } from \"./parseTeam\";\nimport { readInt32, readString } from \"./util\";\n\nexport function parseReplay(fileArrayBuffer: ArrayBuffer): Replay {\n let uint8Ary: Uint8Array = inflateRaw(fileArrayBuffer.slice(headerLength));\n let dataView: DataView = new DataView(uint8Ary.buffer);\n let position = 273;\n let stringLength = readInt32(dataView, position);\n const exeInfo = readString(dataView, position, stringLength);\n let version: number = Number(exeInfo.split(' ')[1]);\n let dictionary = parseField(dataView);\n let gameSetting: GameSetting = {\n allowCheats: dictionary['gameallowcheats'],\n blockade: dictionary['gameblockade'],\n playerCount: dictionary['gamenumplayers'],\n difficulty: dictionary['gamedifficulty'],\n startingAge: dictionary['gamestartingage'],\n endingAge: dictionary['gameendingage'],\n isTreaty: dictionary['gamestartwithtreaty'],\n allowTradeMonopoly: dictionary['gametrademonopoly'],\n gameType: dictionary['gametype'],\n mapCRC: dictionary['gamefilecrc'],\n mapName: dictionary['gamefilename'],\n mapSet: dictionary['gamefilenameext'],\n freeForAll: dictionary['gamefreeforall'],\n hostTime: dictionary['gamehosttime'],\n koth: dictionary['gamekoth'],\n latency: dictionary['gamelatency'],\n mapSetName: dictionary['gamemapname'],\n mapResource: dictionary['gamemapresources'],\n radomSeed: dictionary['gamerandomseed'],\n gameSpeed: dictionary['gamespeed'],\n }\n\n let players: Player[] = [];\n for (let i = 1; i <= gameSetting.playerCount; i++) {\n let player: Player = {\n aiPersonality: dictionary[`gameplayer${i}aipersonality`],\n avatarId: dictionary[`gameplayer${i}avatarid`],\n civId: dictionary[`gameplayer${i}civ`],\n civIsRandom: dictionary[`gameplayer${i}civwasrandom`],\n clan: dictionary[`gameplayer${i}clan`],\n color: dictionary[`gameplayer${i}color`],\n explorerName: dictionary[`gameplayer${i}explorername`],\n explorerSkinId: dictionary[`gameplayer${i}explorerskinid`],\n handicap: dictionary[`gameplayer${i}handicap`],\n homecityFileName: dictionary[`gameplayer${i}hcfilename`],\n homecityLevel: dictionary[`gameplayer${i}hclevel`],\n homecityName: dictionary[`gameplayer${i}homecityname`],\n slotId: dictionary[`gameplayer${i}id`],\n playerName: dictionary[`gameplayer${i}name`],\n initialDecks: [],\n }\n players.push(player);\n }\n\n // initial decks\n players.sort((a, b) => a.slotId - b.slotId);\n let deckIndex: number = 0;\n let allDecks: Deck[] = parseDeck(dataView, uint8Ary);\n for (let i = 0; i < players.length; i++) {\n let initialDecks: Deck[] = [];\n let previousDeckId: number = allDecks[0].deckId;\n while (deckIndex < allDecks.length) {\n if (allDecks[deckIndex].deckId < previousDeckId) {\n break;\n }\n if (allDecks[deckIndex].deckName == '*') {\n break;\n }\n initialDecks.push(allDecks[deckIndex]);\n previousDeckId = allDecks[deckIndex].deckId;\n deckIndex++;\n }\n while (deckIndex < allDecks.length) {\n if (allDecks[deckIndex].deckId == 0) {\n break;\n }\n deckIndex++;\n }\n players[i].initialDecks = initialDecks;\n }\n\n // get teams\n let teams: Team[] = parseTeam(dataView, uint8Ary);\n\n let replay: Replay = {\n exeVersion: version,\n setting: gameSetting,\n players: players,\n teams: teams,\n }\n\n return replay;\n}","import { Team } from \"./dataStructures\";\nimport { search, readInt32, readString } from \"./util\";\n\nexport function parseTeam(dataView: DataView, uint8Ary: Uint8Array): Team[] {\n let teams: Team[] = [];\n let seachBytes = [0x54, 0x45];\n let position = 0;\n while (true) {\n position = search(uint8Ary, seachBytes, position);\n if (position == -1) break;\n position += 6;\n const key = readInt32(dataView, position);\n position += 4;\n if (key == 12) {\n const teamId = readInt32(dataView, position);\n position += 4;\n let stringLength = readInt32(dataView, position);\n position += 4;\n const teamName = readString(dataView, position, stringLength);\n position += stringLength * 2;\n let members: number[] = [];\n const teamMembersCount = readInt32(dataView, position);\n position += 4;\n for (let i = 0; i < teamMembersCount; i++) {\n const slotId = readInt32(dataView, position);\n position += 4;\n members.push(slotId);\n }\n teams.push({\n id: teamId,\n name: teamName,\n members: members\n })\n }\n }\n return teams;\n}"],"mappings":"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","names":["search","import_pako"]} \ No newline at end of file +{"version":3,"sources":["../src/index.ts","../src/parseChat.ts","../src/constant.ts","../src/util.ts","../src/parseDeck.ts","../src/parseField.ts","../src/parseReplay.ts","../src/parseTeam.ts"],"sourcesContent":["import { Deck, GameSetting, Message, Player, Replay, Team } from \"./dataStructures\";\nimport { parseChat } from \"./parseChat\";\nimport { parseDeck } from \"./parseDeck\";\nimport { parseField } from \"./parseField\";\nimport { parseReplay } from \"./parseReplay\";\nimport { parseTeam } from \"./parseTeam\";\n\nexport {\n parseChat,\n parseDeck,\n parseField,\n parseReplay,\n parseTeam,\n Replay,\n GameSetting,\n Player,\n Team,\n Deck,\n Message\n}","import { inflateRaw } from \"pako\";\nimport { Message } from \"./dataStructures\";\nimport { readInt32, readInt8, readString, search } from \"./util\";\nimport { headerLength } from \"./constant\";\n\nexport function parseChat(fileArrayBuffer: ArrayBuffer): Message[] {\n let uint8Ary: Uint8Array = inflateRaw(fileArrayBuffer.slice(headerLength));\n let dataView: DataView = new DataView(uint8Ary.buffer);\n let chat: Message[] = [];\n let searchBytes = [0x9a, 0x99, 0x99, 0x3d];\n let position = search(uint8Ary, searchBytes) + 142;\n const msgLen = readInt32(dataView, position);\n position += 4;\n // starting messages\n for (let i = 0; i < msgLen; i++) {\n let from = readInt32(dataView, position); // from\n position += 4;\n let to = readInt32(dataView, position); // to\n position += 4;\n const bufLen = readInt32(dataView, position);\n position += 4;\n let msg = readString(dataView, position, bufLen);\n position += bufLen * 2;\n position += 1;\n chat.push({\n fromId: from,\n toId: to,\n message: msg,\n time: 0,\n });\n }\n\n let duration: number = 0;\n searchBytes = [0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x19];\n while (true) {\n position = search(uint8Ary, searchBytes, position);\n if (position == -1) break;\n position += 113;\n const command = readInt8(dataView, position);\n position += 1;\n switch (command) {\n case 33:\n case 65:\n case 161:\n case 193:\n break;\n case 1:\n case 129:\n break;\n case 35:\n case 37:\n case 41:\n case 67:\n case 73:\n case 163:\n case 165:\n case 169:\n case 195:\n case 201:\n position += 4;\n break;\n case 3:\n case 5:\n case 9:\n case 131:\n case 133:\n case 137:\n position += 4;\n break;\n case 39:\n case 43:\n case 45:\n case 75:\n case 167:\n case 171:\n case 173:\n case 203:\n position += 8;\n break;\n case 7:\n case 11:\n case 13:\n case 135:\n case 139:\n case 141:\n position += 8;\n break;\n case 47:\n case 175:\n case 207:\n position += 12;\n break;\n case 15:\n case 143:\n position += 12;\n break;\n case 49:\n case 177:\n position += 36;\n break;\n case 17:\n case 145:\n position += 36;\n break;\n case 19:\n case 21:\n case 25:\n case 147:\n case 149:\n case 153:\n position += 40;\n break;\n case 51:\n case 53:\n case 57:\n case 179:\n case 181:\n case 185:\n position += 40;\n break;\n case 55:\n case 59:\n case 61:\n case 183:\n case 187:\n case 189:\n position += 44;\n break;\n case 23:\n case 27:\n case 29:\n case 151:\n case 155:\n case 157:\n position += 44;\n break;\n case 63:\n case 191:\n case 223:\n position += 48;\n break;\n case 31:\n case 159:\n position += 48;\n break;\n default:\n console.error(`Unknown main command: ${command}`);\n position = search(uint8Ary, searchBytes, position)\n continue\n }\n\n const messageCount = readInt32(dataView, position);\n position += 4;\n\n for (let i = 0; i < messageCount; i++) {\n const from = readInt32(dataView, position);\n position += 4;\n const to = readInt32(dataView, position);\n position += 4;\n let bufLen = readInt32(dataView, position);\n position += 4;\n const msg = readString(dataView, position, bufLen);\n position += bufLen * 2;\n position += 1;\n chat.push({\n fromId: from,\n toId: to,\n message: msg,\n time: duration,\n });\n }\n\n duration += readInt8(dataView, position);\n position += 1;\n }\n return chat;\n}","export const headerLength: number = 10;\nexport const decoder = new TextDecoder('utf-16');\nexport const englishRegex: RegExp = /^[A-Za-z0-9_]*$/;","import { decoder } from \"./constant\";\n\nexport function readString(dataView: DataView, position: number, length: number): string {\n const end = position + length * 2;\n const string = decoder.decode(dataView.buffer.slice(position, end));\n return string\n}\n\nexport function readInt32(dataView: DataView, position: number): number {\n const int32 = dataView.getInt32(position, true);\n return int32\n}\n\nexport function readFloat32(dataView: DataView, position: number): number {\n const float32 = dataView.getFloat32(position, true)\n return float32;\n}\n\nexport function readBool(dataView: DataView, position: number): boolean {\n const bool = dataView.getUint8(position);\n return Boolean(bool);\n}\n\nexport function readInt8(dataView: DataView, position: number): number {\n const int8 = dataView.getUint8(position)\n return int8\n}\n\nexport function searchDeck(dataView: DataView, uint8Ary: Uint8Array, startIndex: number): number {\n let position = startIndex;\n while (position < uint8Ary.length) {\n position = search(uint8Ary, [0x0, 0x0, 0x0, 0x44, 0x6b], position);\n if (position == -1) break;\n position += 9;\n let int = readInt32(dataView, position);\n if (int != 5) continue;\n return position - 4;\n }\n return -1;\n}\n\nexport function search(array: Uint8Array, search: number[], fromIndex: number = 0): number {\n const searchLen = search.length\n const searchLast = search[searchLen - 1]\n let index = array.indexOf(searchLast, fromIndex + searchLen - 1)\n\n while (index !== -1) {\n for (let i = searchLen - 1; i > 0; i--) {\n if (search[i - 1] !== array[index - searchLen + i]) {\n const searchIndex = search.lastIndexOf(array[index + 1])\n const offset = searchIndex === -1 ? index + searchLen + 1 : index + searchLen - searchIndex\n index = array.indexOf(searchLast, offset)\n break;\n }\n if (i === 1) return index - searchLen + 1\n }\n }\n return -1\n}","import { Deck } from \"./dataStructures\";\nimport { readInt32, searchDeck, readString, readBool } from \"./util\";\n\nexport function parseDeck(dataView: DataView, uint8Ary: Uint8Array): Deck[] {\n let decks: Deck[] = [];\n let position = 0;\n while (true) {\n let currentDeckPosition: number = position;\n let nextDeckOffset: number = readInt32(dataView, position);\n position += 4;\n let check: number = readInt32(dataView, position);\n position += 4;\n if (check != 5) {\n // if check isn't 5, it's not a deck\n position = searchDeck(dataView, uint8Ary, position);\n if (position == -1) break;\n continue;\n }\n let deckId: number = readInt32(dataView, position);\n position += 4;\n let stringLength: number = readInt32(dataView, position);\n position += 4;\n let deckName: string = readString(dataView, position, stringLength);\n position += stringLength * 2;\n var gameId = readInt32(dataView, position);\n position += 4;\n var isDefault = readBool(dataView, position);\n position += 1;\n let unKnownBool = readBool(dataView, position);\n position += 1;\n var cardCount = readInt32(dataView, position);\n position += 4;\n let techIds: number[] = [];\n for (let j = 0; j < cardCount; j++) {\n let techId = readInt32(dataView, position);\n techIds.push(techId);\n position += 4;\n }\n\n let deck: Deck = {\n deckName: deckName,\n deckId: deckId,\n gameId: gameId,\n isDefault: isDefault,\n cardCount: cardCount,\n techIds: techIds,\n };\n decks.push(deck);\n position = currentDeckPosition + nextDeckOffset + 6;\n }\n return decks;\n}","import { englishRegex } from \"./constant\";\nimport { readString, readInt32, readFloat32, readBool } from \"./util\";\n\nexport function parseField(dataView: DataView): { [k: string]: any } {\n let dictionary: { [k: string]: any } = {};\n let position = 0;\n let endPosition = 20000; // the position of the fields won't exceed this number\n let skipCount: number = 0;\n while (position < endPosition) {\n let word = readString(dataView, position, 1);\n if (englishRegex.test(word)) {\n if (skipCount >= 4) {\n let isNextWord = true;\n let nextWordLength: number = readInt32(dataView, position - 4);\n let nextWord = readString(dataView, position, nextWordLength);\n for (let char of nextWord) {\n if (!englishRegex.test(char)) {\n isNextWord = false;\n break;\n }\n }\n if (isNextWord) {\n position += nextWord.length * 2;\n let dataType = readInt32(dataView, position);\n position += 4;\n let data: any;\n switch (dataType) {\n case 1:\n data = readFloat32(dataView, position);\n position += 4;\n dictionary[nextWord] = data;\n break;\n case 2:\n data = readInt32(dataView, position);\n position += 4;\n dictionary[nextWord] = data;\n break;\n case 5:\n let bool = readBool(dataView, position);\n position += 1;\n dictionary[nextWord] = bool;\n break;\n case 9:\n let stringLength = readInt32(dataView, position);\n if (stringLength > 100) {\n position -= 4;\n // if stringLength is very long, it's most likely not a field.\n break;\n }\n position += 4;\n let string = readString(dataView, position, stringLength);\n position += stringLength * 2;\n dictionary[nextWord] = string;\n break;\n }\n } else {\n position += 2;\n }\n skipCount = 0;\n } else {\n position += 2;\n }\n } else {\n position += 1;\n skipCount += 1;\n }\n }\n return dictionary;\n}","import { inflateRaw } from \"pako\";\nimport { headerLength } from \"./constant\";\nimport { Replay, GameSetting, Player, Deck, Team } from \"./dataStructures\";\nimport { parseDeck } from \"./parseDeck\";\nimport { parseField } from \"./parseField\";\nimport { parseTeam } from \"./parseTeam\";\nimport { readInt32, readString } from \"./util\";\n\nexport function parseReplay(fileArrayBuffer: ArrayBuffer): Replay {\n let uint8Ary: Uint8Array = inflateRaw(fileArrayBuffer.slice(headerLength));\n let dataView: DataView = new DataView(uint8Ary.buffer);\n let position = 273;\n let stringLength = readInt32(dataView, position);\n const exeInfo = readString(dataView, position, stringLength);\n let version: number = Number(exeInfo.split(' ')[1]);\n let dictionary = parseField(dataView);\n let gameSetting: GameSetting = {\n allowCheats: dictionary['gameallowcheats'],\n blockade: dictionary['gameblockade'],\n playerCount: dictionary['gamenumplayers'],\n difficulty: dictionary['gamedifficulty'],\n startingAge: dictionary['gamestartingage'],\n endingAge: dictionary['gameendingage'],\n isTreaty: dictionary['gamestartwithtreaty'],\n allowTradeMonopoly: dictionary['gametrademonopoly'],\n gameType: dictionary['gametype'],\n mapCRC: dictionary['gamefilecrc'],\n mapName: dictionary['gamefilename'],\n mapSet: dictionary['gamefilenameext'],\n freeForAll: dictionary['gamefreeforall'],\n hostTime: dictionary['gamehosttime'],\n koth: dictionary['gamekoth'],\n latency: dictionary['gamelatency'],\n mapSetName: dictionary['gamemapname'],\n mapResource: dictionary['gamemapresources'],\n radomSeed: dictionary['gamerandomseed'],\n gameSpeed: dictionary['gamespeed'],\n }\n\n let players: Player[] = [];\n for (let i = 1; i <= gameSetting.playerCount; i++) {\n let player: Player = {\n aiPersonality: dictionary[`gameplayer${i}aipersonality`],\n avatarId: dictionary[`gameplayer${i}avatarid`],\n civId: dictionary[`gameplayer${i}civ`],\n civIsRandom: dictionary[`gameplayer${i}civwasrandom`],\n clan: dictionary[`gameplayer${i}clan`],\n color: dictionary[`gameplayer${i}color`],\n explorerName: dictionary[`gameplayer${i}explorername`],\n explorerSkinId: dictionary[`gameplayer${i}explorerskinid`],\n handicap: dictionary[`gameplayer${i}handicap`],\n homecityFileName: dictionary[`gameplayer${i}hcfilename`],\n homecityLevel: dictionary[`gameplayer${i}hclevel`],\n homecityName: dictionary[`gameplayer${i}homecityname`],\n slotId: dictionary[`gameplayer${i}id`],\n playerName: dictionary[`gameplayer${i}name`],\n initialDecks: [],\n }\n players.push(player);\n }\n\n // initial decks\n players.sort((a, b) => a.slotId - b.slotId);\n let deckIndex: number = 0;\n let allDecks: Deck[] = parseDeck(dataView, uint8Ary);\n for (let i = 0; i < players.length; i++) {\n let initialDecks: Deck[] = [];\n let previousDeckId: number = allDecks[0].deckId;\n while (deckIndex < allDecks.length) {\n if (allDecks[deckIndex].deckId < previousDeckId) {\n break;\n }\n if (allDecks[deckIndex].deckName == '*') {\n break;\n }\n initialDecks.push(allDecks[deckIndex]);\n previousDeckId = allDecks[deckIndex].deckId;\n deckIndex++;\n }\n while (deckIndex < allDecks.length) {\n if (allDecks[deckIndex].deckId == 0) {\n break;\n }\n deckIndex++;\n }\n players[i].initialDecks = initialDecks;\n }\n\n // get teams\n let teams: Team[] = parseTeam(dataView, uint8Ary);\n\n let replay: Replay = {\n exeVersion: version,\n setting: gameSetting,\n players: players,\n teams: teams,\n }\n\n return replay;\n}","import { Team } from \"./dataStructures\";\nimport { search, readInt32, readString } from \"./util\";\n\nexport function parseTeam(dataView: DataView, uint8Ary: Uint8Array): Team[] {\n let teams: Team[] = [];\n let seachBytes = [0x54, 0x45];\n let position = 0;\n while (true) {\n position = search(uint8Ary, seachBytes, position);\n if (position == -1) break;\n position += 6;\n const key = readInt32(dataView, position);\n position += 4;\n if (key == 12) {\n const teamId = readInt32(dataView, position);\n position += 4;\n let stringLength = readInt32(dataView, position);\n position += 4;\n const teamName = readString(dataView, position, stringLength);\n position += stringLength * 2;\n let members: number[] = [];\n const teamMembersCount = readInt32(dataView, position);\n position += 4;\n for (let i = 0; i < teamMembersCount; i++) {\n const slotId = readInt32(dataView, position);\n position += 4;\n members.push(slotId);\n }\n teams.push({\n id: teamId,\n name: teamName,\n members: members\n })\n }\n }\n return teams;\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kBAA2B;;;ACApB,IAAM,eAAuB;AAC7B,IAAM,UAAU,IAAI,YAAY,QAAQ;AACxC,IAAM,eAAuB;;;ACA7B,SAAS,WAAW,UAAoB,UAAkB,QAAwB;AACrF,QAAM,MAAM,WAAW,SAAS;AAChC,QAAM,SAAS,QAAQ,OAAO,SAAS,OAAO,MAAM,UAAU,GAAG,CAAC;AAClE,SAAO;AACX;AAEO,SAAS,UAAU,UAAoB,UAA0B;AACpE,QAAM,QAAQ,SAAS,SAAS,UAAU,IAAI;AAC9C,SAAO;AACX;AAEO,SAAS,YAAY,UAAoB,UAA0B;AACtE,QAAM,UAAU,SAAS,WAAW,UAAU,IAAI;AAClD,SAAO;AACX;AAEO,SAAS,SAAS,UAAoB,UAA2B;AACpE,QAAM,OAAO,SAAS,SAAS,QAAQ;AACvC,SAAO,QAAQ,IAAI;AACvB;AAEO,SAAS,SAAS,UAAoB,UAA0B;AACnE,QAAM,OAAO,SAAS,SAAS,QAAQ;AACvC,SAAO;AACX;AAEO,SAAS,WAAW,UAAoB,UAAsB,YAA4B;AAC7F,MAAI,WAAW;AACf,SAAO,WAAW,SAAS,QAAQ;AAC/B,eAAW,OAAO,UAAU,CAAC,GAAK,GAAK,GAAK,IAAM,GAAI,GAAG,QAAQ;AACjE,QAAI,YAAY;AAAI;AACpB,gBAAY;AACZ,QAAI,MAAM,UAAU,UAAU,QAAQ;AACtC,QAAI,OAAO;AAAG;AACd,WAAO,WAAW;AAAA,EACtB;AACA,SAAO;AACX;AAEO,SAAS,OAAO,OAAmBA,SAAkB,YAAoB,GAAW;AACvF,QAAM,YAAYA,QAAO;AACzB,QAAM,aAAaA,QAAO,YAAY,CAAC;AACvC,MAAI,QAAQ,MAAM,QAAQ,YAAY,YAAY,YAAY,CAAC;AAE/D,SAAO,UAAU,IAAI;AACjB,aAAS,IAAI,YAAY,GAAG,IAAI,GAAG,KAAK;AACpC,UAAIA,QAAO,IAAI,CAAC,MAAM,MAAM,QAAQ,YAAY,CAAC,GAAG;AAChD,cAAM,cAAcA,QAAO,YAAY,MAAM,QAAQ,CAAC,CAAC;AACvD,cAAM,SAAS,gBAAgB,KAAK,QAAQ,YAAY,IAAI,QAAQ,YAAY;AAChF,gBAAQ,MAAM,QAAQ,YAAY,MAAM;AACxC;AAAA,MACJ;AACA,UAAI,MAAM;AAAG,eAAO,QAAQ,YAAY;AAAA,IAC5C;AAAA,EACJ;AACA,SAAO;AACX;;;AFrDO,SAAS,UAAU,iBAAyC;AAC/D,MAAI,eAAuB,wBAAW,gBAAgB,MAAM,YAAY,CAAC;AACzE,MAAI,WAAqB,IAAI,SAAS,SAAS,MAAM;AACrD,MAAI,OAAkB,CAAC;AACvB,MAAI,cAAc,CAAC,KAAM,KAAM,KAAM,EAAI;AACzC,MAAI,WAAW,OAAO,UAAU,WAAW,IAAI;AAC/C,QAAM,SAAS,UAAU,UAAU,QAAQ;AAC3C,cAAY;AAEZ,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC7B,QAAI,OAAO,UAAU,UAAU,QAAQ;AACvC,gBAAY;AACZ,QAAI,KAAK,UAAU,UAAU,QAAQ;AACrC,gBAAY;AACZ,UAAM,SAAS,UAAU,UAAU,QAAQ;AAC3C,gBAAY;AACZ,QAAI,MAAM,WAAW,UAAU,UAAU,MAAM;AAC/C,gBAAY,SAAS;AACrB,gBAAY;AACZ,SAAK,KAAK;AAAA,MACN,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,IACV,CAAC;AAAA,EACL;AAEA,MAAI,WAAmB;AACvB,gBAAc,CAAC,GAAK,GAAK,GAAK,GAAK,GAAK,GAAK,GAAK,GAAK,GAAK,EAAI;AAChE,SAAO,MAAM;AACT,eAAW,OAAO,UAAU,aAAa,QAAQ;AACjD,QAAI,YAAY;AAAI;AACpB,gBAAY;AACZ,UAAM,UAAU,SAAS,UAAU,QAAQ;AAC3C,gBAAY;AACZ,YAAQ,SAAS;AAAA,MACb,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACD;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AACD;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACD,oBAAY;AACZ;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACD,oBAAY;AACZ;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACD,oBAAY;AACZ;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACD,oBAAY;AACZ;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACD,oBAAY;AACZ;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AACD,oBAAY;AACZ;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AACD,oBAAY;AACZ;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AACD,oBAAY;AACZ;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACD,oBAAY;AACZ;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACD,oBAAY;AACZ;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACD,oBAAY;AACZ;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACD,oBAAY;AACZ;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACD,oBAAY;AACZ;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AACD,oBAAY;AACZ;AAAA,MACJ;AACI,gBAAQ,MAAM,yBAAyB,OAAO,EAAE;AAChD,mBAAW,OAAO,UAAU,aAAa,QAAQ;AACjD;AAAA,IACR;AAEA,UAAM,eAAe,UAAU,UAAU,QAAQ;AACjD,gBAAY;AAEZ,aAAS,IAAI,GAAG,IAAI,cAAc,KAAK;AACnC,YAAM,OAAO,UAAU,UAAU,QAAQ;AACzC,kBAAY;AACZ,YAAM,KAAK,UAAU,UAAU,QAAQ;AACvC,kBAAY;AACZ,UAAI,SAAS,UAAU,UAAU,QAAQ;AACzC,kBAAY;AACZ,YAAM,MAAM,WAAW,UAAU,UAAU,MAAM;AACjD,kBAAY,SAAS;AACrB,kBAAY;AACZ,WAAK,KAAK;AAAA,QACN,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,MACV,CAAC;AAAA,IACL;AAEA,gBAAY,SAAS,UAAU,QAAQ;AACvC,gBAAY;AAAA,EAChB;AACA,SAAO;AACX;;;AG7KO,SAAS,UAAU,UAAoB,UAA8B;AACxE,MAAI,QAAgB,CAAC;AACrB,MAAI,WAAW;AACf,SAAO,MAAM;AACT,QAAI,sBAA8B;AAClC,QAAI,iBAAyB,UAAU,UAAU,QAAQ;AACzD,gBAAY;AACZ,QAAI,QAAgB,UAAU,UAAU,QAAQ;AAChD,gBAAY;AACZ,QAAI,SAAS,GAAG;AAEZ,iBAAW,WAAW,UAAU,UAAU,QAAQ;AAClD,UAAI,YAAY;AAAI;AACpB;AAAA,IACJ;AACA,QAAI,SAAiB,UAAU,UAAU,QAAQ;AACjD,gBAAY;AACZ,QAAI,eAAuB,UAAU,UAAU,QAAQ;AACvD,gBAAY;AACZ,QAAI,WAAmB,WAAW,UAAU,UAAU,YAAY;AAClE,gBAAY,eAAe;AAC3B,QAAI,SAAS,UAAU,UAAU,QAAQ;AACzC,gBAAY;AACZ,QAAI,YAAY,SAAS,UAAU,QAAQ;AAC3C,gBAAY;AACZ,QAAI,cAAc,SAAS,UAAU,QAAQ;AAC7C,gBAAY;AACZ,QAAI,YAAY,UAAU,UAAU,QAAQ;AAC5C,gBAAY;AACZ,QAAI,UAAoB,CAAC;AACzB,aAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AAChC,UAAI,SAAS,UAAU,UAAU,QAAQ;AACzC,cAAQ,KAAK,MAAM;AACnB,kBAAY;AAAA,IAChB;AAEA,QAAI,OAAa;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AACA,UAAM,KAAK,IAAI;AACf,eAAW,sBAAsB,iBAAiB;AAAA,EACtD;AACA,SAAO;AACX;;;AChDO,SAAS,WAAW,UAA0C;AACjE,MAAI,aAAmC,CAAC;AACxC,MAAI,WAAW;AACf,MAAI,cAAc;AAClB,MAAI,YAAoB;AACxB,SAAO,WAAW,aAAa;AAC3B,QAAI,OAAO,WAAW,UAAU,UAAU,CAAC;AAC3C,QAAI,aAAa,KAAK,IAAI,GAAG;AACzB,UAAI,aAAa,GAAG;AAChB,YAAI,aAAa;AACjB,YAAI,iBAAyB,UAAU,UAAU,WAAW,CAAC;AAC7D,YAAI,WAAW,WAAW,UAAU,UAAU,cAAc;AAC5D,iBAAS,QAAQ,UAAU;AACvB,cAAI,CAAC,aAAa,KAAK,IAAI,GAAG;AAC1B,yBAAa;AACb;AAAA,UACJ;AAAA,QACJ;AACA,YAAI,YAAY;AACZ,sBAAY,SAAS,SAAS;AAC9B,cAAI,WAAW,UAAU,UAAU,QAAQ;AAC3C,sBAAY;AACZ,cAAI;AACJ,kBAAQ,UAAU;AAAA,YACd,KAAK;AACD,qBAAO,YAAY,UAAU,QAAQ;AACrC,0BAAY;AACZ,yBAAW,QAAQ,IAAI;AACvB;AAAA,YACJ,KAAK;AACD,qBAAO,UAAU,UAAU,QAAQ;AACnC,0BAAY;AACZ,yBAAW,QAAQ,IAAI;AACvB;AAAA,YACJ,KAAK;AACD,kBAAI,OAAO,SAAS,UAAU,QAAQ;AACtC,0BAAY;AACZ,yBAAW,QAAQ,IAAI;AACvB;AAAA,YACJ,KAAK;AACD,kBAAI,eAAe,UAAU,UAAU,QAAQ;AAC/C,kBAAI,eAAe,KAAK;AACpB,4BAAY;AAEZ;AAAA,cACJ;AACA,0BAAY;AACZ,kBAAI,SAAS,WAAW,UAAU,UAAU,YAAY;AACxD,0BAAY,eAAe;AAC3B,yBAAW,QAAQ,IAAI;AACvB;AAAA,UACR;AAAA,QACJ,OAAO;AACH,sBAAY;AAAA,QAChB;AACA,oBAAY;AAAA,MAChB,OAAO;AACH,oBAAY;AAAA,MAChB;AAAA,IACJ,OAAO;AACH,kBAAY;AACZ,mBAAa;AAAA,IACjB;AAAA,EACJ;AACA,SAAO;AACX;;;ACpEA,IAAAC,eAA2B;;;ACGpB,SAAS,UAAU,UAAoB,UAA8B;AACxE,MAAI,QAAgB,CAAC;AACrB,MAAI,aAAa,CAAC,IAAM,EAAI;AAC5B,MAAI,WAAW;AACf,SAAO,MAAM;AACT,eAAW,OAAO,UAAU,YAAY,QAAQ;AAChD,QAAI,YAAY;AAAI;AACpB,gBAAY;AACZ,UAAM,MAAM,UAAU,UAAU,QAAQ;AACxC,gBAAY;AACZ,QAAI,OAAO,IAAI;AACX,YAAM,SAAS,UAAU,UAAU,QAAQ;AAC3C,kBAAY;AACZ,UAAI,eAAe,UAAU,UAAU,QAAQ;AAC/C,kBAAY;AACZ,YAAM,WAAW,WAAW,UAAU,UAAU,YAAY;AAC5D,kBAAY,eAAe;AAC3B,UAAI,UAAoB,CAAC;AACzB,YAAM,mBAAmB,UAAU,UAAU,QAAQ;AACrD,kBAAY;AACZ,eAAS,IAAI,GAAG,IAAI,kBAAkB,KAAK;AACvC,cAAM,SAAS,UAAU,UAAU,QAAQ;AAC3C,oBAAY;AACZ,gBAAQ,KAAK,MAAM;AAAA,MACvB;AACA,YAAM,KAAK;AAAA,QACP,IAAI;AAAA,QACJ,MAAM;AAAA,QACN;AAAA,MACJ,CAAC;AAAA,IACL;AAAA,EACJ;AACA,SAAO;AACX;;;AD5BO,SAAS,YAAY,iBAAsC;AAC9D,MAAI,eAAuB,yBAAW,gBAAgB,MAAM,YAAY,CAAC;AACzE,MAAI,WAAqB,IAAI,SAAS,SAAS,MAAM;AACrD,MAAI,WAAW;AACf,MAAI,eAAe,UAAU,UAAU,QAAQ;AAC/C,QAAM,UAAU,WAAW,UAAU,UAAU,YAAY;AAC3D,MAAI,UAAkB,OAAO,QAAQ,MAAM,GAAG,EAAE,CAAC,CAAC;AAClD,MAAI,aAAa,WAAW,QAAQ;AACpC,MAAI,cAA2B;AAAA,IAC3B,aAAa,WAAW,iBAAiB;AAAA,IACzC,UAAU,WAAW,cAAc;AAAA,IACnC,aAAa,WAAW,gBAAgB;AAAA,IACxC,YAAY,WAAW,gBAAgB;AAAA,IACvC,aAAa,WAAW,iBAAiB;AAAA,IACzC,WAAW,WAAW,eAAe;AAAA,IACrC,UAAU,WAAW,qBAAqB;AAAA,IAC1C,oBAAoB,WAAW,mBAAmB;AAAA,IAClD,UAAU,WAAW,UAAU;AAAA,IAC/B,QAAQ,WAAW,aAAa;AAAA,IAChC,SAAS,WAAW,cAAc;AAAA,IAClC,QAAQ,WAAW,iBAAiB;AAAA,IACpC,YAAY,WAAW,gBAAgB;AAAA,IACvC,UAAU,WAAW,cAAc;AAAA,IACnC,MAAM,WAAW,UAAU;AAAA,IAC3B,SAAS,WAAW,aAAa;AAAA,IACjC,YAAY,WAAW,aAAa;AAAA,IACpC,aAAa,WAAW,kBAAkB;AAAA,IAC1C,WAAW,WAAW,gBAAgB;AAAA,IACtC,WAAW,WAAW,WAAW;AAAA,EACrC;AAEA,MAAI,UAAoB,CAAC;AACzB,WAAS,IAAI,GAAG,KAAK,YAAY,aAAa,KAAK;AAC/C,QAAI,SAAiB;AAAA,MACjB,eAAe,WAAW,aAAa,CAAC,eAAe;AAAA,MACvD,UAAU,WAAW,aAAa,CAAC,UAAU;AAAA,MAC7C,OAAO,WAAW,aAAa,CAAC,KAAK;AAAA,MACrC,aAAa,WAAW,aAAa,CAAC,cAAc;AAAA,MACpD,MAAM,WAAW,aAAa,CAAC,MAAM;AAAA,MACrC,OAAO,WAAW,aAAa,CAAC,OAAO;AAAA,MACvC,cAAc,WAAW,aAAa,CAAC,cAAc;AAAA,MACrD,gBAAgB,WAAW,aAAa,CAAC,gBAAgB;AAAA,MACzD,UAAU,WAAW,aAAa,CAAC,UAAU;AAAA,MAC7C,kBAAkB,WAAW,aAAa,CAAC,YAAY;AAAA,MACvD,eAAe,WAAW,aAAa,CAAC,SAAS;AAAA,MACjD,cAAc,WAAW,aAAa,CAAC,cAAc;AAAA,MACrD,QAAQ,WAAW,aAAa,CAAC,IAAI;AAAA,MACrC,YAAY,WAAW,aAAa,CAAC,MAAM;AAAA,MAC3C,cAAc,CAAC;AAAA,IACnB;AACA,YAAQ,KAAK,MAAM;AAAA,EACvB;AAGA,UAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAC1C,MAAI,YAAoB;AACxB,MAAI,WAAmB,UAAU,UAAU,QAAQ;AACnD,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACrC,QAAI,eAAuB,CAAC;AAC5B,QAAI,iBAAyB,SAAS,CAAC,EAAE;AACzC,WAAO,YAAY,SAAS,QAAQ;AAChC,UAAI,SAAS,SAAS,EAAE,SAAS,gBAAgB;AAC7C;AAAA,MACJ;AACA,UAAI,SAAS,SAAS,EAAE,YAAY,KAAK;AACrC;AAAA,MACJ;AACA,mBAAa,KAAK,SAAS,SAAS,CAAC;AACrC,uBAAiB,SAAS,SAAS,EAAE;AACrC;AAAA,IACJ;AACA,WAAO,YAAY,SAAS,QAAQ;AAChC,UAAI,SAAS,SAAS,EAAE,UAAU,GAAG;AACjC;AAAA,MACJ;AACA;AAAA,IACJ;AACA,YAAQ,CAAC,EAAE,eAAe;AAAA,EAC9B;AAGA,MAAI,QAAgB,UAAU,UAAU,QAAQ;AAEhD,MAAI,SAAiB;AAAA,IACjB,YAAY;AAAA,IACZ,SAAS;AAAA,IACT;AAAA,IACA;AAAA,EACJ;AAEA,SAAO;AACX;","names":["search","import_pako"]} \ No newline at end of file diff --git a/package.json b/package.json index a6606f6..7c03ccb 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "test": "jest" }, "name": "@canyougiant/aoe3de-replay-parser", - "version": "1.3.3", + "version": "1.3.4", "description": "Parsing Age3Yrec file of AOE3DE", "repository": { "type": "git", diff --git a/src/index.ts b/src/index.ts index 4d047a1..5784386 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,20 @@ +import { Deck, GameSetting, Message, Player, Replay, Team } from "./dataStructures"; import { parseChat } from "./parseChat"; import { parseDeck } from "./parseDeck"; import { parseField } from "./parseField"; import { parseReplay } from "./parseReplay"; import { parseTeam } from "./parseTeam"; -export { parseChat, parseDeck, parseField, parseReplay, parseTeam } \ No newline at end of file +export { + parseChat, + parseDeck, + parseField, + parseReplay, + parseTeam, + Replay, + GameSetting, + Player, + Team, + Deck, + Message +} \ No newline at end of file