/// <summary> /// Returns a list of packet properties for writing and reading packets. /// /// </summary> /// <param name="type">Type to check the properties of.</param> /// <returns>List of properties to write.</returns> /// <exception cref="InvalidOperationException">Properties are invalid.</exception> public static StructPacketProperty GetPacketProperties(Type type) { // Populate the cache entry if needed. CachePacketPropertiesSemaphore.Wait(); if (!CachePacketProperties.ContainsKey(type)) { CachePacketProperties[type] = new StructPacketProperty(type); } CachePacketPropertiesSemaphore.Release(); // Return the cache entry. return(CachePacketProperties[type]); }
/// <summary> /// Creates the struct packet property. /// </summary> /// <param name="structType">Type of the struct.</param> public StructPacketProperty(Type structType) { // Add the packet information. if (structType.GetCustomAttribute(typeof(PacketStructAttribute)) is PacketStructAttribute packetStruct) { this.Properties.Add(new PacketInformation(packetStruct.MessageIdentifier, packetStruct.RemoteConnectionType, packetStruct.PacketId)); } // Convert the properties to PacketProperties. foreach (var property in structType?.GetProperties()) { // Create the base packet property. IPacketProperty packetProperty = null; if (property.PropertyType == typeof(string)) { packetProperty = new StringPacketProperty(property); } else if (property.PropertyType == typeof(Quaternion) && property.GetCustomAttribute <NiQuaternionAttribute>() != null) { packetProperty = new NiQuaternionProperty(property); } else if (property.PropertyType.IsValueType && property.PropertyType.GetCustomAttribute <StructAttribute>() != null) { packetProperty = new StructPacketProperty(property); } else { packetProperty = new PacketProperty(property); } if ((property.GetCustomAttribute(typeof(DefaultAttribute)) is DefaultAttribute defaultAttribute)) { packetProperty = new FlagPacketProperty(packetProperty, defaultAttribute.ValueToIgnore); } // Wrap the required properties. var requiredProperties = new Dictionary <string, RequiredPacketProperty>(); foreach (var requiredAttribute in property.GetCustomAttributes <RequiresAttribute>()) { if (!requiredProperties.ContainsKey(requiredAttribute.PropertyName)) { var requiredPacketProperty = new RequiredPacketProperty(packetProperty, requiredAttribute.PropertyName); requiredProperties.Add(requiredAttribute.PropertyName, requiredPacketProperty); packetProperty = requiredPacketProperty; } requiredProperties[requiredAttribute.PropertyName].RequiredValues.Add(requiredAttribute.ValueToRequire); } // Add the packet property. this.Properties.Add(packetProperty); } }
/// <summary> /// Creates the packet property. /// </summary> /// <param name="property">Property to write.</param> public PacketProperty(PropertyInfo property) { // Store the property. this.StructProperty = property; // Get the type to write. if (property == null) { return; } this._propertyType = property.PropertyType; if (this._propertyType.IsEnum) { this._propertyType = Enum.GetUnderlyingType(this._propertyType); } // Get the custom writer and reader. var readerWriterType = this._propertyType; if (readerWriterType.IsArray) { readerWriterType = readerWriterType.GetElementType(); } if (readerWriterType != null) { // Set the writer and reader for types. foreach (var(customWriterType, customWriter) in CustomWriters) { if (customWriterType == readerWriterType || readerWriterType.IsSubclassOf(customWriterType)) { this._customWriter = customWriter; } } foreach (var(customReaderType, customReader) in CustomReaders) { if (customReaderType == readerWriterType || readerWriterType.IsSubclassOf(customReaderType)) { this._customReader = customReader; } } // Set the writer and reader for structs. if (readerWriterType.IsValueType && readerWriterType.GetCustomAttribute <StructAttribute>() != null) { var structPacketProperty = new StructPacketProperty(readerWriterType); this._customWriter = ((writer, o) => { structPacketProperty.Write(o, writer, null); }); this._customReader = ((reader, context) => { var o = Activator.CreateInstance(readerWriterType); var writtenProperties = new Dictionary <string, object>(); structPacketProperty.Read(o, reader, writtenProperties, context); return(o); }); } } // Get the array length type. if (property.GetCustomAttribute(typeof(StoreLengthAsAttribute)) is StoreLengthAsAttribute storeLengthAs) { this._arrayLengthPropertyType = storeLengthAs.Type; } }