private object ReadDataType(RepLayoutCmdType replayout, NetBitReader netBitReader, Type objectType = null) { object data = null; switch (replayout) { case RepLayoutCmdType.Property: data = _linqCache.CreateObject(objectType); (data as IProperty).Serialize(netBitReader); (data as IResolvable)?.Resolve(GuidCache); break; case RepLayoutCmdType.PropertyBool: data = netBitReader.SerializePropertyBool(); break; case RepLayoutCmdType.PropertyName: data = netBitReader.SerializePropertyName(); break; case RepLayoutCmdType.PropertyFloat: data = netBitReader.SerializePropertyFloat(); break; case RepLayoutCmdType.PropertyNativeBool: data = netBitReader.SerializePropertyNativeBool(); break; case RepLayoutCmdType.PropertyNetId: data = netBitReader.SerializePropertyNetId(); break; case RepLayoutCmdType.PropertyObject: data = netBitReader.SerializePropertyObject(); break; case RepLayoutCmdType.PropertyPlane: throw new NotImplementedException("Plane RepLayoutCmdType not implemented"); case RepLayoutCmdType.PropertyRotator: data = netBitReader.SerializePropertyRotator(); break; case RepLayoutCmdType.PropertyString: data = netBitReader.SerializePropertyString(); break; case RepLayoutCmdType.PropertyVector10: data = netBitReader.SerializePropertyVector10(); break; case RepLayoutCmdType.PropertyVector100: data = netBitReader.SerializePropertyVector100(); break; case RepLayoutCmdType.PropertyVectorNormal: data = netBitReader.SerializePropertyVectorNormal(); break; case RepLayoutCmdType.PropertyVectorQ: data = netBitReader.SerializePropertyQuantizedVector(VectorQuantization.RoundWholeNumber); break; case RepLayoutCmdType.RepMovement: data = netBitReader.SerializeRepMovement(); break; case RepLayoutCmdType.Enum: data = netBitReader.SerializePropertyEnum(); break; // TODO Auto generation fix to handle 1-8 bits case RepLayoutCmdType.PropertyByte: data = netBitReader.ReadByte(); break; case RepLayoutCmdType.PropertyInt: data = netBitReader.ReadInt32(); break; case RepLayoutCmdType.PropertyInt16: data = netBitReader.ReadInt16(); break; case RepLayoutCmdType.PropertyUInt64: data = netBitReader.ReadUInt64(); break; case RepLayoutCmdType.PropertyUInt16: data = netBitReader.ReadUInt16(); break; case RepLayoutCmdType.PropertyUInt32: data = netBitReader.ReadUInt32(); break; case RepLayoutCmdType.PropertyVector: data = netBitReader.SerializePropertyVector(); break; case RepLayoutCmdType.PropertyVector2D: data = netBitReader.SerializePropertyVector2D(); break; default: netBitReader.Seek(netBitReader.GetBitsLeft(), System.IO.SeekOrigin.Current); break; } return(data); }
/// <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); } }
/// <summary> /// Tries to read the property and update the value accordingly. /// </summary> /// <param name="obj"></param> /// <param name="export"></param> /// <param name="handle"></param> /// <param name="exportGroup"></param> /// <param name="netBitReader"></param> public void ReadField(object obj, NetFieldExport export, uint handle, NetFieldExportGroup exportGroup, NetBitReader netBitReader) { if (!_netFieldGroups.TryGetValue(exportGroup.PathName, out var netGroupInfo)) { return; } NetFieldInfo netFieldInfo; if (netGroupInfo.UsesHandles) { if (!netGroupInfo.Handles.TryGetValue(handle, out netFieldInfo)) { return; } } else { if (!netGroupInfo.Properties.TryGetValue(export.Name, out netFieldInfo)) { return; } } SetType(obj, exportGroup, netFieldInfo, netBitReader); }
private void SetType(object obj, NetFieldExportGroup exportGroup, NetFieldInfo netFieldInfo, NetBitReader netBitReader) { var data = netFieldInfo.Attribute.Type switch { RepLayoutCmdType.DynamicArray => ReadArrayField(exportGroup, netFieldInfo, netBitReader), RepLayoutCmdType.RepMovement => netFieldInfo.MovementAttribute != null?netBitReader.SerializeRepMovement( locationQuantizationLevel : netFieldInfo.MovementAttribute.LocationQuantizationLevel, rotationQuantizationLevel : netFieldInfo.MovementAttribute.RotationQuantizationLevel, velocityQuantizationLevel : netFieldInfo.MovementAttribute.VelocityQuantizationLevel) : netBitReader.SerializeRepMovement(), _ => ReadDataType(netFieldInfo.Attribute.Type, netBitReader, netFieldInfo.PropertyInfo.PropertyType), }; if (data != null && !netBitReader.IsError) { var typeAccessor = TypeAccessor.Create(obj.GetType()); typeAccessor[obj, netFieldInfo.PropertyInfo.Name] = data; } }
private static void AddUnknownField(string exportName, string exportType, string group, uint handle, NetBitReader netBitReader) { HashSet <UnknownFieldInfo> fields = new HashSet <UnknownFieldInfo>(); if (!UnknownNetFields.TryAdd(group, fields)) { UnknownNetFields.TryGetValue(group, out fields); } fields.Add(new UnknownFieldInfo(FixInvalidNames(exportName), exportType, netBitReader.GetBitsLeft(), handle)); }
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); } }
private static void SetType(object obj, Type netType, NetFieldInfo netFieldInfo, NetFieldExportGroup exportGroup, NetBitReader netBitReader) { object data = null; switch (netFieldInfo.Attribute.Type) { case RepLayoutCmdType.DynamicArray: data = ReadArrayField(obj, exportGroup, netFieldInfo, netBitReader); break; default: data = ReadDataType(netFieldInfo.Attribute.Type, netBitReader, netFieldInfo.PropertyInfo.PropertyType); break; } if (data != null) { TypeAccessor typeAccessor = TypeAccessor.Create(netType); typeAccessor[obj, netFieldInfo.PropertyInfo.Name] = data; } }
private static object ReadDataType(RepLayoutCmdType replayout, NetBitReader netBitReader, Type objectType = null) { object data = null; switch (replayout) { case RepLayoutCmdType.Property: data = Activator.CreateInstance(objectType); (data as IProperty).Serialize(netBitReader); break; case RepLayoutCmdType.PropertyBool: data = netBitReader.SerializePropertyBool(); break; case RepLayoutCmdType.PropertyName: netBitReader.Seek(netBitReader.Position + netBitReader.GetBitsLeft()); break; case RepLayoutCmdType.PropertyFloat: data = netBitReader.SerializePropertyFloat(); break; case RepLayoutCmdType.PropertyNativeBool: data = netBitReader.SerializePropertyNativeBool(); break; case RepLayoutCmdType.PropertyNetId: data = netBitReader.SerializePropertyNetId(); break; case RepLayoutCmdType.PropertyObject: data = netBitReader.SerializePropertyObject(); break; case RepLayoutCmdType.PropertyPlane: throw new NotImplementedException("Plane RepLayoutCmdType not implemented"); case RepLayoutCmdType.PropertyRotator: data = netBitReader.SerializePropertyRotator(); break; case RepLayoutCmdType.PropertyString: data = netBitReader.SerializePropertyString(); break; case RepLayoutCmdType.PropertyVector10: data = netBitReader.SerializePropertyVector10(); break; case RepLayoutCmdType.PropertyVector100: data = netBitReader.SerializePropertyVector100(); break; case RepLayoutCmdType.PropertyVectorNormal: data = netBitReader.SerializePropertyVectorNormal(); break; case RepLayoutCmdType.PropertyVectorQ: data = netBitReader.SerializePropertyQuantizeVector(); break; case RepLayoutCmdType.RepMovement: data = netBitReader.SerializeRepMovement(); break; case RepLayoutCmdType.Enum: data = netBitReader.SerializeEnum(); break; //Auto generation fix to handle 1-8 bits case RepLayoutCmdType.PropertyByte: data = (byte)netBitReader.ReadBitsToInt(netBitReader.GetBitsLeft()); break; //Auto generation fix to handle 1-32 bits. case RepLayoutCmdType.PropertyInt: data = netBitReader.ReadBitsToInt(netBitReader.GetBitsLeft()); break; case RepLayoutCmdType.PropertyUInt64: data = netBitReader.ReadUInt64(); break; case RepLayoutCmdType.PropertyUInt16: data = (ushort)netBitReader.ReadBitsToInt(netBitReader.GetBitsLeft()); break; case RepLayoutCmdType.PropertyUInt32: data = netBitReader.ReadUInt32(); break; case RepLayoutCmdType.Pointer: switch (netBitReader.GetBitsLeft()) { case 8: data = (uint)netBitReader.ReadByte(); break; case 16: data = (uint)netBitReader.ReadUInt16(); break; case 32: data = netBitReader.ReadUInt32(); break; } break; case RepLayoutCmdType.PropertyVector: data = new FVector(netBitReader.ReadSingle(), netBitReader.ReadSingle(), netBitReader.ReadSingle()); break; case RepLayoutCmdType.Ignore: netBitReader.Seek(netBitReader.Position + netBitReader.GetBitsLeft()); break; } return(data); }
public static void ReadField(object obj, NetFieldExport export, NetFieldExportGroup exportGroup, uint handle, NetBitReader netBitReader) { string group = exportGroup.PathName; string fixedExportName = FixInvalidNames(export.Name); if (!_netFieldGroups.ContainsKey(group)) { AddUnknownField(fixedExportName, export?.Type, group, handle, netBitReader); return; } Type netType = _netFieldGroups[group]; NetFieldGroupInfo netGroupInfo = _netFieldGroupInfo[netType]; if (!netGroupInfo.Properties.ContainsKey(fixedExportName)) { AddUnknownField(fixedExportName, export?.Type, group, handle, netBitReader); return; } NetFieldInfo netFieldInfo = netGroupInfo.Properties[fixedExportName]; //Update if it finds a higher bit count or an actual type if (!String.IsNullOrEmpty(export.Type)) { if (String.IsNullOrEmpty(netFieldInfo.Attribute.Info.Type)) { AddUnknownField(fixedExportName, export?.Type, group, handle, netBitReader); } } /*else if(netFieldInfo.Attribute.Info.BitCount < netBitReader.GetBitsLeft()) * { * if(String.IsNullOrEmpty(netFieldInfo.Attribute.Info.Type)) * { * AddUnknownField(fixedExportName, export?.Type, group, handle, netBitReader); * } * }*/ SetType(obj, netType, netFieldInfo, exportGroup, netBitReader); }