private void AddNetFieldInfo(Type type, NetFieldGroupInfo info) { foreach (var property in type.GetProperties()) { var netFieldExportAttribute = property.GetCustomAttribute <NetFieldExportAttribute>(); var handleAttribute = property.GetCustomAttribute <NetFieldExportHandleAttribute>(); if (netFieldExportAttribute == null && handleAttribute == null) { continue; } if (netFieldExportAttribute != null) { info.Properties[netFieldExportAttribute.Name] = new NetFieldInfo { MovementAttribute = property.GetCustomAttribute <RepMovementAttribute>(), Attribute = netFieldExportAttribute, PropertyInfo = property }; } else { info.UsesHandles = true; info.Handles[handleAttribute.Handle] = new NetFieldInfo { MovementAttribute = property.GetCustomAttribute <RepMovementAttribute>(), Attribute = handleAttribute, PropertyInfo = property }; } } }
static NetFieldParser() { IEnumerable <Type> netFields = Assembly.GetExecutingAssembly().GetTypes().Where(x => x.GetCustomAttribute <NetFieldExportGroupAttribute>() != null); foreach (Type type in netFields) { NetFieldExportGroupAttribute attribute = type.GetCustomAttribute <NetFieldExportGroupAttribute>(); if (attribute != null) { _netFieldGroups[attribute.Path] = type; } NetFieldGroupInfo info = new NetFieldGroupInfo(); _netFieldGroupInfo[type] = info; foreach (PropertyInfo property in type.GetProperties()) { NetFieldExportAttribute netFieldExportAttribute = property.GetCustomAttribute <NetFieldExportAttribute>(); if (netFieldExportAttribute == null) { continue; } info.Properties[netFieldExportAttribute.Name] = new NetFieldInfo { Attribute = netFieldExportAttribute, PropertyInfo = property }; } } //Type layout for dynamic arrays _primitiveTypeLayout.Add(typeof(bool), RepLayoutCmdType.PropertyBool); _primitiveTypeLayout.Add(typeof(byte), RepLayoutCmdType.PropertyByte); _primitiveTypeLayout.Add(typeof(ushort), RepLayoutCmdType.PropertyUInt16); _primitiveTypeLayout.Add(typeof(int), RepLayoutCmdType.PropertyInt); _primitiveTypeLayout.Add(typeof(uint), RepLayoutCmdType.PropertyUInt32); _primitiveTypeLayout.Add(typeof(ulong), RepLayoutCmdType.PropertyUInt64); _primitiveTypeLayout.Add(typeof(float), RepLayoutCmdType.PropertyFloat); _primitiveTypeLayout.Add(typeof(string), RepLayoutCmdType.PropertyString); IEnumerable <Type> iPropertyTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes()) .Where(x => typeof(IProperty).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract); //Allows deserializing IProperty type arrays foreach (var iPropertyType in iPropertyTypes) { _primitiveTypeLayout.Add(iPropertyType, RepLayoutCmdType.Property); } _primitiveTypeLayout.Add(typeof(object), RepLayoutCmdType.Ignore); AddDefaultExportGroups(); }
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); }
/// <summary> /// Create a NetFieldParser, which will load all <see cref="NetFieldExportGroup"/> in the <see cref="AppDomain.CurrentDomain"/>. /// </summary> /// <param name="cache">Instance of NetGuidCache, used to resolve netguids to their string value.</param> /// <param name="mode"></param> /// <param name="assemblyNameFilter">Found assemblies should contain this string.</param> public NetFieldParser(NetGuidCache cache, ParseMode mode, string assemblyNameFilter = "ReplayReader") { GuidCache = cache; var types = AppDomain.CurrentDomain.GetAssemblies().Where(a => a.FullName.Contains(assemblyNameFilter) || a.FullName.Contains("Unreal.Core")).SelectMany(i => i.GetTypes()); var netFields = types.Where(c => c.GetCustomAttribute <NetFieldExportGroupAttribute>() != null); foreach (var type in netFields) { var attribute = type.GetCustomAttribute <NetFieldExportGroupAttribute>(); if (attribute.MinimalParseMode <= mode) { var info = new NetFieldGroupInfo { Type = type }; _netFieldGroups[attribute.Path] = info; AddNetFieldInfo(type, info); } } // Allows deserializing type arrays var netSubFields = types.Where(c => c.GetCustomAttribute <NetFieldExportSubGroupAttribute>() != null); foreach (var type in netSubFields) { var attribute = type.GetCustomAttribute <NetFieldExportSubGroupAttribute>(); if (attribute.MinimalParseMode <= mode) { var info = _netFieldGroups[attribute.Path]; AddNetFieldInfo(type, info); } } // ClassNetCaches var classNetCaches = types.Where(c => c.GetCustomAttribute <NetFieldExportClassNetCacheAttribute>() != null); foreach (var type in classNetCaches) { var attribute = type.GetCustomAttribute <NetFieldExportClassNetCacheAttribute>(); if (attribute.MinimalParseMode <= mode) { var info = new ClassNetCacheInfo(); AddClassNetInfo(type, info); _classNetCacheToNetFieldGroup[attribute.Path] = info; } } // PlayerControllers var controllers = types.Where(c => c.GetCustomAttribute <PlayerControllerAttribute>() != null); foreach (var type in controllers) { var attribute = type.GetCustomAttribute <PlayerControllerAttribute>(); PlayerControllerGroups.Add(attribute.Path); } //Type layout for dynamic arrays _primitiveTypeLayout.Add(typeof(bool), RepLayoutCmdType.PropertyBool); _primitiveTypeLayout.Add(typeof(byte), RepLayoutCmdType.PropertyByte); _primitiveTypeLayout.Add(typeof(ushort), RepLayoutCmdType.PropertyUInt16); _primitiveTypeLayout.Add(typeof(int), RepLayoutCmdType.PropertyInt); _primitiveTypeLayout.Add(typeof(uint), RepLayoutCmdType.PropertyUInt32); _primitiveTypeLayout.Add(typeof(ulong), RepLayoutCmdType.PropertyUInt64); _primitiveTypeLayout.Add(typeof(float), RepLayoutCmdType.PropertyFloat); _primitiveTypeLayout.Add(typeof(string), RepLayoutCmdType.PropertyString); // Allows deserializing type arrays var iPropertyTypes = types.Where(x => typeof(IProperty).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract); foreach (var iPropertyType in iPropertyTypes) { _primitiveTypeLayout.Add(iPropertyType, RepLayoutCmdType.Property); } _primitiveTypeLayout.Add(typeof(object), RepLayoutCmdType.Ignore); }
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); } }