private void AddClassNetInfo(Type type, ClassNetCacheInfo info) { foreach (var property in type.GetProperties()) { var structAttribute = property.GetCustomAttribute <NetFieldExportRPCAttribute>(); if (structAttribute != null) { info.Properties[structAttribute.Name] = new ClassNetCachePropertyInfo() { PropertyInfo = property, Name = structAttribute.Name, PathName = structAttribute.PathName, IsFunction = structAttribute.IsFunction, EnablePropertyChecksum = structAttribute.EnablePropertyChecksum, IsCustomStruct = structAttribute.CustomStruct }; } } }
/// <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); }