/// <summary> /// Parses combat related data /// </summary> private IEnumerable <ParsedCombatItem> ParseCombatItems(int revision, ByteArrayBinaryReader reader) { switch (revision) { case 0: // 64 bytes: each combat item while (reader.Length - reader.Position >= 64) { ParsedCombatItem combatItem = ReadCombatItemRevision0(reader); yield return(combatItem); } break; case 1: // 64 bytes: each combat item while (reader.Length - reader.Position >= 64) { ParsedCombatItem combatItem = ReadCombatItemRevision1(reader); yield return(combatItem); } break; default: throw new NotSupportedException("Only EVTC revisions 0 and 1 are supported."); } }
/// <summary> /// Reads raw data from the bytes of an EVTC log. /// </summary> /// <param name="bytes">The contents of an uncompressed EVTC log, as bytes.</param> /// <exception cref="LogParsingException">Thrown when parsing fails due to a malformed log.</exception> /// <returns>The raw data from the log.</returns> public ParsedLog ParseLog(byte[] bytes) { var reader = new ByteArrayBinaryReader(bytes, Encoding.UTF8); LogVersion logVersion; ParsedBossData bossData; List <ParsedAgent> agents; List <ParsedSkill> skills; List <ParsedCombatItem> combatItems; try { logVersion = ParseLogData(reader); } catch (Exception e) { throw new LogParsingException("Failed to parse log metadata.", e); } try { bossData = ParseBossData(reader); } catch (Exception e) { throw new LogParsingException("Failed to parse boss data.", e); } try { agents = ParseAgents(reader).ToList(); } catch (Exception e) { throw new LogParsingException("Failed to parse agents.", e); } try { skills = ParseSkills(reader).ToList(); } catch (Exception e) { throw new LogParsingException("Failed to parse skills.", e); } try { combatItems = ParseCombatItems(logVersion.Revision, reader).ToList(); } catch (Exception e) { throw new LogParsingException("Failed to parse combat items.", e); } return(new ParsedLog(logVersion, bossData, agents, skills, combatItems)); }
private LogVersion ParseLogData(ByteArrayBinaryReader reader) { // 12 bytes: arc build version string buildVersion = reader.ReadString(12); // 1 byte: revision byte revision = reader.ReadByte(); return(new LogVersion(buildVersion, revision)); }
/// <summary> /// Parses boss related data. /// </summary> private ParsedBossData ParseBossData(ByteArrayBinaryReader reader) { // 2 bytes: boss species ID ushort id = reader.ReadUInt16(); // 1 byte: unused reader.Skip(1); return(new ParsedBossData(id)); }
public ParsedLog ParseLog(byte[] bytes) { var reader = new ByteArrayBinaryReader(bytes, Encoding.UTF8); var logVersion = ParseLogData(reader); var bossData = ParseBossData(reader); var agents = ParseAgents(reader).ToList(); var skills = ParseSkills(reader).ToList(); var combatItems = ParseCombatItems(logVersion.Revision, reader).ToList(); return(new ParsedLog(logVersion, bossData, agents, skills, combatItems)); }
/// <summary> /// Parses skill related data /// </summary> private IEnumerable <ParsedSkill> ParseSkills(ByteArrayBinaryReader reader) { // 4 bytes: skill count int skillCount = reader.ReadInt32(); // 68 bytes: each skill for (int i = 0; i < skillCount; i++) { // 4 bytes: skill ID int skillId = reader.ReadInt32(); // 64 bytes: name var name = reader.ReadString(64); var skill = new ParsedSkill(skillId, name); yield return(skill); } }
/// <summary> /// Parses agent related data /// </summary> private IEnumerable <ParsedAgent> ParseAgents(ByteArrayBinaryReader reader) { // 4 bytes: agent count int agentCount = reader.ReadInt32(); // 96 bytes: each agent for (int i = 0; i < agentCount; i++) { // 8 bytes: agent address ulong address = reader.ReadUInt64(); // 4 bytes: profession uint prof = reader.ReadUInt32(); // 4 bytes: is_elite uint isElite = reader.ReadUInt32(); // 2 bytes: toughness int toughness = reader.ReadInt16(); // 2 bytes: concentration int concentration = reader.ReadInt16(); // 2 bytes: healing int healing = reader.ReadInt16(); // 2 bytes: hb_width int hitboxWidth = reader.ReadInt16(); // 2 bytes: condition int condition = reader.ReadInt16(); // 2 bytes: hb_height int hitboxHeight = reader.ReadInt16(); // 68 bytes: name String name = reader.ReadString(68); ParsedAgent parsedAgent = new ParsedAgent(address, name, prof, isElite, toughness, concentration, healing, condition, hitboxWidth, hitboxHeight); yield return(parsedAgent); } }
private static ParsedCombatItem ReadCombatItemRevision1(ByteArrayBinaryReader reader) { // 8 bytes: time long time = reader.ReadInt64(); // 8 bytes: src_agent ulong srcAgent = reader.ReadUInt64(); // 8 bytes: dst_agent ulong dstAgent = reader.ReadUInt64(); // 4 bytes: value int value = reader.ReadInt32(); // 4 bytes: buff_dmg int buffDmg = reader.ReadInt32(); // 4 bytes: overstack_value uint overstackValue = reader.ReadUInt32(); // 4 bytes: skill_id uint skillId = reader.ReadUInt32(); // 2 bytes: src_instid ushort srcInstid = reader.ReadUInt16(); // 2 bytes: dst_instid ushort dstInstid = reader.ReadUInt16(); // 2 bytes: src_master_instid ushort srcMasterInstid = reader.ReadUInt16(); // 2 bytes: dst_master_instid ushort dstMasterInstid = reader.ReadUInt16(); // 1 byte: iff FriendOrFoe iff = GetFriendOrFoeFromByte(reader.ReadByte()); // 1 byte: buff byte buff = reader.ReadByte(); // 1 byte: result Result result = GetResultFromByte(reader.ReadByte()); // 1 byte: is_activation Activation isActivation = GetActivationFromByte(reader.ReadByte()); // 1 byte: is_buffremove BuffRemove isBuffRemove = GetBuffRemoveFromByte(reader.ReadByte()); // 1 byte: is_ninety byte isNinety = reader.ReadByte(); // 1 byte: is_fifty byte isFifty = reader.ReadByte(); // 1 byte: is_moving byte isMoving = reader.ReadByte(); // 1 byte: is_statechange StateChange isStateChange = GetStateChangeFromByte(reader.ReadByte()); // 1 byte: is_flanking byte isFlanking = reader.ReadByte(); // 1 byte: is_shields byte isShields = reader.ReadByte(); // 1 byte: is_offcycle byte isOffcycle = reader.ReadByte(); // 4 bytes: "padding" uint padding = reader.ReadUInt32(); return(new ParsedCombatItem(time, srcAgent, dstAgent, value, buffDmg, overstackValue, skillId, srcInstid, dstInstid, srcMasterInstid, dstMasterInstid, iff, buff, result, isActivation, isBuffRemove, isNinety, isFifty, isMoving, isStateChange, isFlanking, isShields, isOffcycle, padding)); }