public static Entity Load(byte[] data) { if (data.Length < 16) { ErrorManager.SignalError("Entity: Data is too short"); } int length = BitConv.FromInt32(data, 0); int blank1 = BitConv.FromInt32(data, 4); int blank2 = BitConv.FromInt32(data, 8); int propertycount = BitConv.FromInt32(data, 12); if (length != data.Length) { ErrorManager.SignalIgnorableError("Entity: Length field mismatch"); } if (blank1 != 0 || blank2 != 0) { ErrorManager.SignalIgnorableError("Entity: Blank value is wrong"); } if (propertycount < 0 || propertycount > ushort.MaxValue) { ErrorManager.SignalError("Entity: Property count is invalid"); } if (data.Length < 16 + propertycount * 8) { ErrorManager.SignalError("Entity: Data is too short"); } Dictionary <short, EntityProperty> properties = new Dictionary <short, EntityProperty>(); for (int i = 0; i < propertycount; i++) { short id = BitConv.FromInt16(data, 16 + i * 8); int offset = (ushort)BitConv.FromInt16(data, 18 + i * 8) + 12; int nextoffset = (i == propertycount - 1) ? data.Length : ((ushort)BitConv.FromInt16(data, 26 + i * 8) + 12); byte type = data[20 + i * 8]; byte elementsize = data[21 + i * 8]; short unknown = BitConv.FromInt16(data, 22 + i * 8); if (offset > data.Length) { ErrorManager.SignalError("Entity: Property begins out of bounds"); } if (nextoffset < offset) { ErrorManager.SignalError("Entity: Property ends before it begins"); } if (nextoffset > data.Length) { ErrorManager.SignalError("Entity: Property ends out of bounds"); } if (properties.ContainsKey(id)) { ErrorManager.SignalIgnorableError("Entity: Duplicate property"); } else { byte[] propertydata = new byte [nextoffset - offset]; Array.Copy(data, offset, propertydata, 0, propertydata.Length); EntityProperty property = EntityProperty.Load(type, elementsize, unknown, i == propertycount - 1, propertydata); properties.Add(id, property); } } return(new Entity(properties)); }
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)); }