Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public class D2OUnpacker : IFileUnpacker<D2OClass>
- {
- private int _contentPosition;
- private const string FileHeader = "D2O";
- private const string FileSignature = "AKSF";
- public D2OClassDefinition ClassDefinition { get; private set; }
- public IReadOnlyCollection<D2OClass> Unpacked { get; private set; }
- public void Unpack(IReader reader)
- {
- if(!_tryParseHeader(reader)) throw new InvalidOperationException("d2o file is corrupted");
- var classPointers = _parseClassPointers(reader);
- var classCount = reader.ReadValue<int>();
- ClassDefinition = _parseClassDefinition(reader);
- var unpacked = new List<D2OClass>(classCount);
- foreach (var pointer in classPointers)
- {
- reader.Seek(pointer.Value);
- unpacked.Add(_parseClassValues(reader, pointer.Key));
- }
- Unpacked = unpacked;
- }
- #region Private Methods
- private bool _tryParseHeader(IReader reader)
- {
- var fileHeader = Encoding.ASCII.GetString(reader.ReadValues<byte>(3));
- if (fileHeader == FileHeader) return true;
- reader.Seek(0);
- var signature = reader.ReadValue<string>();
- if (signature != FileSignature) return false;
- reader.Seek(6); // skip formatVersion + len
- var realHeader = Encoding.ASCII.GetString(reader.ReadValues<byte>(3));
- return realHeader != FileHeader;
- }
- private Dictionary<int, int> _parseClassPointers(IReader reader)
- {
- var tablePointerPosition = reader.ReadValue<int>();
- reader.Seek(tablePointerPosition + _contentPosition);
- var objectPointersLen = reader.ReadValue<int>();
- var classPointers = new Dictionary<int, int>(objectPointersLen);
- for (var i = 0; i < objectPointersLen; i += 8)
- {
- var key = reader.ReadValue<int>();
- var pointer = reader.ReadValue<int>();
- classPointers[key] = pointer + _contentPosition;
- }
- return classPointers;
- }
- private D2OClassDefinition _parseClassDefinition(IReader reader)
- {
- reader.Skip(4);
- var className = reader.ReadValue<string>();
- var packageName = reader.ReadValue<string>();
- var fieldsCount = reader.ReadValue<int>();
- var fields = new List<D2OFieldDefinition>(fieldsCount);
- for (var i = 0; i < fieldsCount; i++)
- {
- var fieldName = reader.ReadValue<string>();
- var fieldType = (D2OFieldValueType)reader.ReadValue<int>();
- if (fieldType == D2OFieldValueType.Vector)
- {
- reader.SkipString(); // skip inner field name
- fieldType = (D2OFieldValueType)reader.ReadValue<int>();
- fields.Add(new D2OFieldDefinition(fieldName, D2OFieldValueType.Vector, fieldType));
- continue;
- }
- fields.Add(new D2OFieldDefinition(fieldName, fieldType, D2OFieldValueType.None));
- }
- return new D2OClassDefinition(className, packageName, fields);
- }
- private D2OClass _parseClassValues(IReader reader, int classId)
- {
- reader.Skip(4); // skip class identifier
- var fields = new List<D2OField>(ClassDefinition.Fields.Count);
- foreach(var field in ClassDefinition.Fields)
- {
- if (field.Type != D2OFieldValueType.Vector)
- {
- var value = reader.ReadFrom(field.Type);
- fields.Add(new D2OField(field.Name, field.Type, value));
- continue;
- }
- var len = reader.ReadValue<int>();
- var innerFieldValue = new object[len];
- for (var i = 0; i < len; i++)
- innerFieldValue[i] = reader.ReadFrom(field.InnerType);
- fields.Add(new D2OField(field.Name, D2OFieldValueType.Vector, field.Type, innerFieldValue));
- }
- return new D2OClass(classId, fields);
- }
- #endregion
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement