Example #1
0
        /// <summary>
        /// see https://github.com/EpicGames/UnrealEngine/blob/5677c544747daa1efc3b5ede31642176644518a6/Engine/Source/Runtime/Engine/Private/RepLayout.cpp#L3141
        /// </summary>
        private Array ReadArrayField(NetFieldExportGroup netfieldExportGroup, NetFieldInfo fieldInfo, NetBitReader netBitReader)
        {
            var arrayIndexes = netBitReader.ReadIntPacked();

            var elementType    = fieldInfo.PropertyInfo.PropertyType.GetElementType();
            var isPrimitveType = _primitiveTypeLayout.TryGetValue(elementType, out var replayout);

            if (replayout == RepLayoutCmdType.Ignore)
            {
                return(null);
            }

            var arr = Array.CreateInstance(elementType, arrayIndexes);

            while (true)
            {
                var index = netBitReader.ReadIntPacked();

                if (index == 0)
                {
                    // At this point, the 0 either signifies:
                    // An array terminator, at which point we're done.
                    // An array element terminator, which could happen if the array had tailing elements removed.
                    if (netBitReader.GetBitsLeft() == 8)
                    {
                        // We have bits left over, so see if its the Array Terminator.
                        // This should be 0
                        var terminator = netBitReader.ReadIntPacked();

                        if (terminator != 0x00)
                        {
                            //Log error

                            return(arr);
                        }
                    }

                    return(arr);
                }

                // Shift all indexes down since 0 represents null handle
                index--;

                if (index >= arrayIndexes)
                {
                    //Log error
                    return(arr);
                }

                object data = null;

                if (!isPrimitveType)
                {
                    data = _linqCache.CreateObject(elementType);
                }

                while (true)
                {
                    var handle = netBitReader.ReadIntPacked();

                    if (handle == 0)
                    {
                        break;
                    }

                    handle--;

                    if (netfieldExportGroup.NetFieldExports.Length < handle)
                    {
                        return(arr);
                    }

                    var export  = netfieldExportGroup.NetFieldExports[handle];
                    var numBits = netBitReader.ReadIntPacked();

                    if (numBits == 0)
                    {
                        continue;
                    }

                    if (export == null)
                    {
                        netBitReader.SkipBits((int)numBits);
                        continue;
                    }

                    var cmdReader = new NetBitReader(netBitReader.ReadBits(numBits))
                    {
                        EngineNetworkVersion = netBitReader.EngineNetworkVersion,
                        NetworkVersion       = netBitReader.NetworkVersion
                    };

                    if (!isPrimitveType)
                    {
                        ReadField(data, export, handle, netfieldExportGroup, cmdReader);
                    }
                    else
                    {
                        data = ReadDataType(replayout, cmdReader, elementType);
                    }
                }

                arr.SetValue(data, index);
            }
        }
Example #2
0
        private static Array ReadArrayField(object obj, NetFieldExportGroup netfieldExportGroup, NetFieldInfo fieldInfo, NetBitReader netBitReader)
        {
            uint arrayIndexes = netBitReader.ReadIntPacked();

            Type             elementType = fieldInfo.PropertyInfo.PropertyType.GetElementType();
            RepLayoutCmdType replayout   = RepLayoutCmdType.Ignore;

            NetFieldGroupInfo groupInfo = null;

            if (_netFieldGroupInfo.ContainsKey(elementType))
            {
                groupInfo = _netFieldGroupInfo[elementType];
            }
            else
            {
                if (!_primitiveTypeLayout.TryGetValue(elementType, out replayout))
                {
                    replayout = RepLayoutCmdType.Ignore;
                }
                else
                {
                    if (elementType == typeof(DebuggingObject))
                    {
                    }
                }
            }


            Array arr = Array.CreateInstance(elementType, arrayIndexes);

            while (true)
            {
                uint index = netBitReader.ReadIntPacked();

                if (index == 0)
                {
                    if (netBitReader.GetBitsLeft() == 8)
                    {
                        uint terminator = netBitReader.ReadIntPacked();

                        if (terminator != 0x00)
                        {
                            //Log error

                            return(arr);
                        }
                    }

                    return(arr);
                }

                --index;

                if (index >= arrayIndexes)
                {
                    //Log error

                    return(arr);
                }

                object data = null;

                if (groupInfo != null)
                {
                    data = Activator.CreateInstance(elementType);
                }

                while (true)
                {
                    uint handle = netBitReader.ReadIntPacked();

                    if (handle == 0)
                    {
                        break;
                    }

                    handle--;

                    if (netfieldExportGroup.NetFieldExports.Length < handle)
                    {
                        return(arr);
                    }

                    NetFieldExport export  = netfieldExportGroup.NetFieldExports[handle];
                    uint           numBits = netBitReader.ReadIntPacked();

                    if (numBits == 0)
                    {
                        continue;
                    }

                    if (export == null)
                    {
                        netBitReader.SkipBits((int)numBits);

                        continue;
                    }

                    NetBitReader cmdReader = new NetBitReader(netBitReader.ReadBits(numBits))
                    {
                        EngineNetworkVersion = netBitReader.EngineNetworkVersion,
                        NetworkVersion       = netBitReader.NetworkVersion
                    };

                    //Uses the same type for the array
                    if (groupInfo != null)
                    {
                        ReadField(data, export, netfieldExportGroup, handle, cmdReader);
                    }
                    else //Probably primitive values
                    {
                        data = ReadDataType(replayout, cmdReader, elementType);
                    }
                }

                arr.SetValue(data, index);
            }
        }