public override UnprocessedChunk Unprocess(int chunkid) { byte[] data = new byte [Length]; BitConv.ToInt16(data, 0, Magic); BitConv.ToInt16(data, 2, Type); BitConv.ToInt32(data, 4, chunkid); BitConv.ToInt32(data, 8, entries.Count); // Checksum is here, but calculated later int offset = 20 + entries.Count * 4; for (int i = 0; i < entries.Count; i++) { UnprocessedEntry entry = entries[i].Unprocess(); byte[] entrydata = entry.Save(); offset += entry.HeaderLength; Aligner.Align(ref offset, Alignment); offset -= entry.HeaderLength; if (offset + entrydata.Length > Length) { throw new PackingException(); } BitConv.ToInt32(data, 16 + i * 4, offset); entrydata.CopyTo(data, offset); offset += entrydata.Length; } BitConv.ToInt32(data, 16 + entries.Count * 4, offset); int checksum = CalculateChecksum(data); BitConv.ToInt32(data, 12, checksum); return(new UnprocessedChunk(data)); }
public override byte[] Save() { int length = 20 + Items.Count * 4; Aligner.Align(ref length, 4); foreach (byte[] item in Items) { length += item.Length; Aligner.Align(ref length, 4); } byte[] data = new byte [length]; BitConv.ToInt32(data, 0, Magic); BitConv.ToInt32(data, 4, EID); BitConv.ToInt32(data, 8, Type); BitConv.ToInt32(data, 12, Items.Count); int offset = 20 + Items.Count * 4; Aligner.Align(ref offset, 4); BitConv.ToInt32(data, 16, offset); for (int i = 0; i < Items.Count; i++) { Items[i].CopyTo(data, offset); offset += Items[i].Length; Aligner.Align(ref offset, 4); BitConv.ToInt32(data, 20 + i * 4, offset); } return(data); }
public override byte[] Save() { if (rows.Count == 0) { return(new byte [0]); } int length; if (IsSparse) { length = rows.Count * 2; } else { length = 2; } if (HasMetaValues) { length += rows.Count * 2; } Aligner.Align(ref length, 4); foreach (EntityPropertyRow <T> row in rows) { length += row.Values.Count * ElementSize; } Aligner.Align(ref length, 4); byte[] data = new byte [length]; int offset = 0; if (IsSparse) { foreach (EntityPropertyRow <T> row in rows) { BitConv.ToInt16(data, offset, (short)row.Values.Count); offset += 2; } } else { BitConv.ToInt16(data, offset, (short)rows[0].Values.Count); offset += 2; } if (HasMetaValues) { foreach (EntityPropertyRow <T> row in rows) { if (!row.MetaValue.HasValue) { throw new InvalidOperationException("EntityPropertyRow MetaValues must be consistently present or non-present."); } BitConv.ToInt16(data, offset, row.MetaValue.Value); offset += 2; } } Aligner.Align(ref offset, 4); byte[] elementdata = new byte [ElementSize]; foreach (EntityPropertyRow <T> row in rows) { foreach (T value in row.Values) { SaveElement(elementdata, value); elementdata.CopyTo(data, offset); offset += ElementSize; } } return(data); }
public sealed override EntityProperty Load(byte elementsize, short unknown, bool issparse, bool hasmetavalues, byte[] data) { if (elementsize != ElementSize) { ErrorManager.SignalError("EntityProperty: Element size is wrong"); } if (unknown < 0) { ErrorManager.SignalError("EntityProperty: Unknown value is invalid"); } List <EntityPropertyRow <T> > rows = new List <EntityPropertyRow <T> >(); for (int i = 0; i < unknown; i++) { rows.Add(new EntityPropertyRow <T>()); } int offset = 0; if (issparse) { if (offset + 2 * unknown > data.Length) { ErrorManager.SignalError("EntityProperty: Not enough data"); } foreach (EntityPropertyRow <T> row in rows) { int valuecount = (ushort)BitConv.FromInt16(data, offset); offset += 2; for (int i = 0; i < valuecount; i++) { row.Values.Add(new T()); } } } else { if (offset + 2 > data.Length) { ErrorManager.SignalError("EntityProperty: Not enough data"); } int valuecount = (ushort)BitConv.FromInt16(data, offset); offset += 2; foreach (EntityPropertyRow <T> row in rows) { for (int i = 0; i < valuecount; i++) { row.Values.Add(new T()); } } } if (hasmetavalues) { if (offset + 2 * unknown > data.Length) { ErrorManager.SignalError("EntityProperty: Not enough data"); } foreach (EntityPropertyRow <T> row in rows) { short metavalue = BitConv.FromInt16(data, offset); offset += 2; row.MetaValue = metavalue; } } Aligner.Align(ref offset, 4); byte[] elementdata = new byte [elementsize]; foreach (EntityPropertyRow <T> row in rows) { if (offset + row.Values.Count * elementsize > data.Length) { ErrorManager.SignalError("EntityProperty: Not enough data"); } for (int i = 0; i < row.Values.Count; i++) { Array.Copy(data, offset, elementdata, 0, elementsize); offset += elementsize; row.Values[i] = LoadElement(elementdata); } } Aligner.Align(ref offset, 4); if (offset != data.Length) { ErrorManager.SignalIgnorableError("EntityProperty: More data than expected"); } return(Load(rows)); }