Exemple #1
0
        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));
        }
Exemple #2
0
        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));
        }