using System; using System.Collections.Generic; using System.IO; using Oni.Metadata; namespace Oni { internal sealed class InstanceDescriptor { private InstanceFile file; private string fullName; private int index; private Template template; private int dataOffset; private int nameOffset; private int dataSize; private InstanceDescriptorFlags flags; internal static InstanceDescriptor Read(InstanceFile file, BinaryReader reader, int index) { var metadata = InstanceMetadata.GetMetadata(file); var descriptor = new InstanceDescriptor { file = file, index = index, template = metadata.GetTemplate((TemplateTag)reader.ReadInt32()), dataOffset = reader.ReadInt32(), nameOffset = reader.ReadInt32(), dataSize = reader.ReadInt32(), flags = (InstanceDescriptorFlags)(reader.ReadInt32() & 0xff) }; if (descriptor.IsPlaceholder && !descriptor.HasName) throw new InvalidDataException("Empty descriptors must have names"); return descriptor; } public InstanceFile File => file; public int Index => index; public string FullName { get { if (fullName == null) fullName = index.ToString(); return fullName; } } public string Name { get { string name = FullName; if (name.StartsWith(Template.Tag.ToString(), StringComparison.Ordinal)) name = name.Substring(4); return name; } } public Template Template => template; public bool HasName => ((flags & InstanceDescriptorFlags.Private) == 0); public bool IsPlaceholder => ((flags & InstanceDescriptorFlags.Placeholder) != 0 || dataSize == 0 || dataOffset == 0); public int DataOffset => file.Header.DataTableOffset + dataOffset; public int DataSize => dataSize; internal void ReadName(Dictionary names) { if (!HasName) return; if (IsPlaceholder || file.Header.Version == InstanceFileHeader.Version31) { names.TryGetValue(nameOffset, out fullName); } else { fullName = Importer.DecodeFileName(file.FilePath); string tagName = template.Tag.ToString(); if (!fullName.StartsWith(tagName, StringComparison.Ordinal)) fullName = tagName + fullName; } } internal void SetName(string newName) { flags &= ~InstanceDescriptorFlags.Private; fullName = newName; } public List GetReferencedDescriptors() => file.GetReferencedDescriptors(this); internal BinaryReader OpenRead() { if (IsPlaceholder) throw new InvalidOperationException(); return new BinaryReader(file.FilePath, file) { Position = DataOffset }; } internal BinaryReader OpenRead(int offset) { if (IsPlaceholder) throw new InvalidOperationException(); return new BinaryReader(file.FilePath, file) { Position = DataOffset + offset }; } internal BinaryReader GetRawReader(int offset) => file.GetRawReader(offset); internal BinaryReader GetSepReader(int offset) { if (!IsMacFile) return GetRawReader(offset); return file.GetSepReader(offset); } internal bool IsMacFile => (file.Header.TemplateChecksum == InstanceFileHeader.OniMacTemplateChecksum); public long TemplateChecksum => file.Header.TemplateChecksum; public string FilePath => file.FilePath; public bool HasRawParts() { if (IsPlaceholder) return false; switch (template.Tag) { case TemplateTag.AKVA: case TemplateTag.AGDB: case TemplateTag.BINA: case TemplateTag.TXMP: case TemplateTag.OSBD: case TemplateTag.SNDD: case TemplateTag.SUBT: case TemplateTag.TRAM: return true; default: return false; } } } }