private static ICollection<Sc2ReplayAttribute> ParseAttributes(IMpqArchive replay)
        {
            var file = replay.ReadFile("replay.attributes.events");

            using (var stream = new MemoryStream(file))
            {
                stream.Skip(5); // there is a 5-byte header; should we validate this?

                var attributeCount = stream.ReadInt32();
                var attributes = new List<Sc2ReplayAttribute>();

                for (var i = 0; i < attributeCount; i++)
                {
                    var attr = new Sc2ReplayAttribute
                               {
                                   Header = stream.ReadInt32(),
                                   Type = (Sc2ReplayAttributeType) stream.ReadInt32(),
                                   PlayerIndex = stream.ReadByte(),
                                   Value = stream.ReadBytes(4).Reverse().ToArray(),
                               };

                    attributes.Add(attr);
                }

                return attributes;
            }
        }
Example #2
0
        private static Sc2Replay ParseReplay(IMpqArchive archive)
        {
            if (archive == null) throw new ArgumentNullException("archive");

            var result = new Sc2Replay();
            ParseUserDataHeader(archive, result);

            dynamic details = archive.ReadSerializedData("replay.details", false);

            result.MapName = Encoding.UTF8.GetString(details[1]);

            // parse the date, subtract the time zone to get UTC time
            var timeZoneOffset = new TimeSpan((long)details[6]);
            var date = DateTime.FromFileTime((long)details[5]);
            var adjustedDate = date.Subtract(timeZoneOffset);
            result.DatePlayed = DateTime.SpecifyKind(adjustedDate, DateTimeKind.Utc);

            result.Players = ParsePlayers(details);
            ParseMapInformation(details, result);

            // hack: we don't actually parse the replay gateway since I 
            //  haven't been able to find it in the replay file yet.
            //  for now, we just assume that it's the same as the gateway
            //  of the map file resource.
            result.Gateway = result.MapGateway; 

            result.Attributes = ParseAttributes(archive);
            ApplyAttributes(result);
            return result;
        }
Example #3
0
        public static byte[]? ReadFile(this IMpqArchive archive, string path)
        {
            var size = archive.GetFileSize(path);

            if (!size.HasValue)
            {
                return(null);
            }

            var buf = new byte[size.Value];

            archive.ReadFile(buf, path);
            return(buf);
        }
Example #4
0
        public static PooledArray <byte>?ReadFilePool(this IMpqArchive archive, string path)
        {
            var size = archive.GetFileSize(path);

            if (!size.HasValue)
            {
                return(null);
            }

            var buf = new PooledArray <byte>(size.Value);

            archive.ReadFile(buf.AsArray(), path);
            return(buf);
        }
Example #5
0
 private bool TryOpenMpq(out IMpqArchive m)
 {
     try
     {
         m = mpqService.Open();
         return(true);
     }
     catch (Exception e)
     {
         messageBoxService.ShowDialog(new MessageBoxFactory <bool>()
                                      .SetTitle("Invalid MPQ")
                                      .SetMainInstruction("Couldn't parse game MPQ.")
                                      .SetContent(e.Message + "\n\nAre you using modified game files?")
                                      .WithButton("Ok", false)
                                      .Build());
         m = null;
         return(false);
     }
 }
Example #6
0
        public static object ReadSerializedData(this IMpqArchive archive, string path, bool convertStringsToUtf8)
        {
            if (archive == null)
            {
                throw new ArgumentNullException("archive");
            }

            var file = archive.ReadFile(path);

            if (file == null)
            {
                return(null);
            }

            using (var memory = new MemoryStream(file))
                using (var reader = new BinaryReader(memory))
                {
                    return(Deserialize(reader, convertStringsToUtf8));
                }
        }
Example #7
0
        private static void ParseUserDataHeader(IMpqArchive replay, Sc2Replay result)
        {
            dynamic data = Starcraft2SerializedData.Deserialize(replay.UserDataHeader.UserData, true);

            var starcraft2 = (string)data[0];
            if (!starcraft2.StartsWith("StarCraft II replay"))
                // todo: this is kind of a hack, for some reason there are extra funky characters after "replay". Why?
                throw new InvalidOperationException(
                    String.Format(
                        "This does not appear to be a SC2 replay file. (Unexpected user header string: '{0}')",
                        starcraft2));

            var buildAndVersion = (IDictionary<long, object>)data[1];
            result.Version = new[] { (long)buildAndVersion[0], (long)buildAndVersion[1], (long)buildAndVersion[2], (long)buildAndVersion[3] };
            result.Build = new[] { (long)buildAndVersion[4], (long)buildAndVersion[5] };

            ValidateBuild(result.Build);

            var lengthInTicks = (long)data[3];
            result.Length = TimeSpan.FromSeconds(lengthInTicks / 16d);
        }