public AbilityInfo GetAbility(Common.STUGUID key) { STULoadout ability = GetInstance <STULoadout>(key); if (ability == null) { return(null); } return(new AbilityInfo(key, GetString(ability.Name), GetString(ability.Description), ability.Category.ToString())); }
public static Asset Excavate(ushort type, ulong guid) { Asset asset = new Asset { GUID = IO.GetFileName(guid), SerializationType = SerializationType.Unknown }; using (Stream file = IO.OpenFile(guid)) { if (file == null) { return(asset); } using (BinaryReader reader = new BinaryReader(file)) { if (Version1.IsValidVersion(reader)) { reader.BaseStream.Position = 0; asset.SerializationType = SerializationType.STUv1; asset.STUInstances = new HashSet <string>(); asset.GUIDs = new HashSet <string>(); reader.BaseStream.Position = 0; // try and auto detect padding that is before a guid int maxCount = 0; for (int i = 0; i < reader.BaseStream.Length; i++) { byte b = reader.ReadByte(); if (b == 255) { maxCount++; } if (maxCount >= 8 && b != 255) { if (reader.BaseStream.Length - reader.BaseStream.Position > 8) { reader.BaseStream.Position -= 1; // before b Common.STUGUID rawGUID = new Common.STUGUID(reader.ReadUInt64()); reader.BaseStream.Position -= 7; // back to after b if (GUID.Type(rawGUID) > 1) { asset.GUIDs.Add(rawGUID.ToString()); } } } if (b != 255 && maxCount > 0) { maxCount = 0; } } } else if (type == 0xBC) { asset.SerializationType = SerializationType.MapData; asset.GUIDs = new HashSet <string>(); asset.STUInstances = new HashSet <string>(); reader.BaseStream.Position = 0; Map map = new Map(file, uint.MaxValue); foreach (ISTU stu in map.STUs) { asset.GUIDs = new HashSet <string>(asset.GUIDs.Concat(GetGUIDs(stu)).ToList()); foreach (Common.STUInstance stuInstance in stu.Instances) { STUAttribute attr = stuInstance?.GetType().GetCustomAttributes <STUAttribute>().FirstOrDefault(); if (attr == null) { continue; } asset.STUInstances.Add(attr.Checksum.ToString("X8")); } } } else if (type == 0x6) { asset.SerializationType = SerializationType.Raw; reader.BaseStream.Position = 0x18L; ulong effectKey = reader.ReadUInt64(); reader.BaseStream.Position = 0; Animation animation = new Animation(reader.BaseStream); HashSet <string> guids = new HashSet <string>(); if (animation.Header.F08Key != 0) { guids.Add(IO.GetFileName(animation.Header.F08Key)); } if (effectKey != 0) { guids.Add(IO.GetFileName(effectKey)); } asset.GUIDs = guids; } else { if (Version2.IsValidVersion(reader)) // why is there no magic, blizz pls { reader.BaseStream.Position = 0; Version2 stuVersion2 = null; try { stuVersion2 = new Version2(file, uint.MaxValue); asset.SerializationType = SerializationType.STUv2; asset.GUIDs = new HashSet <string>(); asset.STUInstances = new HashSet <string>(); } catch (Exception) { asset.SerializationType = SerializationType.Unknown; } if (stuVersion2 != null) { asset.GUIDs = GetGUIDs(stuVersion2); // broken: todo // foreach (uint typeHash in stuVersion2.TypeHashes) { // asset.STUInstances.Add(typeHash.ToString("X8")); // } asset.JSONDump = ""; StringBuilder sb = new StringBuilder(); int i = 0; foreach (Common.STUInstance stuInstance in stuVersion2.Instances.Concat(stuVersion2.HiddenInstances)) { STUAttribute attr = stuInstance?.GetType().GetCustomAttributes <STUAttribute>().FirstOrDefault(); if (attr == null) { continue; } asset.STUInstances.Add($"{attr.Checksum:X8}"); if (stuInstance.Usage != Common.InstanceUsage.Root) { continue; } if (i != 0) { sb.AppendLine(); } sb.AppendLine($"{attr.Checksum:X8}:"); sb.AppendLine(JsonConvert.SerializeObject(stuInstance, Formatting.Indented)); i++; } asset.JSONDump = sb.ToString(); } } } } } return(asset); }
protected FieldGuessData[] GuessFields(STUInstanceField[] definedFields, BinaryReader reader, uint instanceChecksum = 0) { FieldGuessData[] output = new FieldGuessData[definedFields.Length]; // FieldLocationInfo[] fieldSizes = GetFieldSizes(definedFields, reader); // todo: use this for something uint outputIndex = 0; foreach (STUInstanceField field in definedFields) { FieldGuessData fieldOutput = new FieldGuessData { Size = field.FieldSize, Checksum = field.FieldChecksum }; if (instanceChecksum != 0) { foreach (KeyValuePair <uint, List <ChainedInstanceInfo> > pair in ChainedInstances ) // if (pair.Key != instanceChecksum) continue; { foreach (ChainedInstanceInfo info in pair.Value) { if (info.OwnerChecksum != instanceChecksum || info.OwnerField != field.FieldChecksum) { continue; } fieldOutput.IsChained = true; fieldOutput.ChainedInstanceChecksum = info.Checksum; break; } } } if (field.FieldSize == 0) { TryReadInlineStandard(fieldOutput, reader); TryReadInlineArray(fieldOutput, reader); uint size = reader.ReadUInt32(); reader.BaseStream.Position += size; } else { TryReadArray(fieldOutput, field, reader); if (fieldOutput.IsArray) { TryReadArrayItems(fieldOutput); } long startPosition = reader.BaseStream.Position; using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) { byte[] fieldSHA1Demangle = null; if (field.FieldSize == 8) { Common.STUGUID f = new Common.STUGUID(reader.ReadUInt64()); DemangleInstance(f, field.FieldChecksum); fieldSHA1Demangle = sha1.ComputeHash(BitConverter.GetBytes(f)); // is this bad? reader.BaseStream.Position = startPosition; } byte[] fieldSHA1 = sha1.ComputeHash(reader.ReadBytes((int)field.FieldSize)); fieldOutput.SHA1 = fieldSHA1; fieldOutput.DemangleSHA1 = fieldSHA1Demangle; } } output[outputIndex] = fieldOutput; outputIndex++; } return(output); }