Exemplo n.º 1
0
        internal ComponentType[] GetQueryTypes()
        {
            var types = new HashSet <ComponentType>();

            for (var i = 0; i < m_GroupData->ArchetypeQueryCount; ++i)
            {
                for (var j = 0; j < m_GroupData->ArchetypeQuery[i].AnyCount; ++j)
                {
                    types.Add(TypeManager.GetType(m_GroupData->ArchetypeQuery[i].Any[j]));
                }
                for (var j = 0; j < m_GroupData->ArchetypeQuery[i].AllCount; ++j)
                {
                    types.Add(TypeManager.GetType(m_GroupData->ArchetypeQuery[i].All[j]));
                }
                for (var j = 0; j < m_GroupData->ArchetypeQuery[i].NoneCount; ++j)
                {
                    types.Add(ComponentType.Subtractive(TypeManager.GetType(m_GroupData->ArchetypeQuery[i].None[j])));
                }
            }

            var array = new ComponentType[types.Count];
            var t     = 0;

            foreach (var type in types)
            {
                array[t++] = type;
            }
            return(array);
        }
        static ComponentType[] GetComponentTypes(Type jobType, Type interfaceType, out int processCount,
                                                 out ComponentType[] changedFilter)
        {
            var genericArgs = interfaceType.GetGenericArguments();

            var executeMethodParameters = jobType.GetMethod("Execute").GetParameters();

            var componentTypes     = new List <ComponentType>();
            var changedFilterTypes = new List <ComponentType>();


            // void Execute(Entity entity, int index, ref T0 data0, ref T1 data1, ref T2 data2);
            // First two parameters are optional, depending on the interface name used.
            var methodParameterOffset = genericArgs.Length != executeMethodParameters.Length ? 2 : 0;

            for (var i = 0; i < genericArgs.Length; i++)
            {
                var isReadonly = executeMethodParameters[i + methodParameterOffset].GetCustomAttribute(typeof(ReadOnlyAttribute)) != null;

                var type = new ComponentType(genericArgs[i],
                                             isReadonly ? ComponentType.AccessMode.ReadOnly : ComponentType.AccessMode.ReadWrite);
                componentTypes.Add(type);

                var isChangedFilter = executeMethodParameters[i + methodParameterOffset].GetCustomAttribute(typeof(ChangedFilterAttribute)) != null;
                if (isChangedFilter)
                {
                    changedFilterTypes.Add(type);
                }
            }

            var subtractive = jobType.GetCustomAttribute <RequireSubtractiveComponentAttribute>();

            if (subtractive != null)
            {
                foreach (var type in subtractive.SubtractiveComponents)
                {
                    componentTypes.Add(ComponentType.Subtractive(type));
                }
            }

            var requiredTags = jobType.GetCustomAttribute <RequireComponentTagAttribute>();

            if (requiredTags != null)
            {
                foreach (var type in requiredTags.TagComponents)
                {
                    componentTypes.Add(ComponentType.ReadOnly(type));
                }
            }

            processCount  = genericArgs.Length;
            changedFilter = changedFilterTypes.ToArray();
            return(componentTypes.ToArray());
        }
Exemplo n.º 3
0
        private static ComponentType[] GetComponentTypes(Type jobType, Type interfaceType, out int processCount,
                                                         out ComponentType[] changedFilter)
        {
            var genericArgs = interfaceType.GetGenericArguments();

            var executeMethodParameters = jobType.GetMethod("Execute").GetParameters();

            var componentTypes     = new List <ComponentType>();
            var changedFilterTypes = new List <ComponentType>();

            for (var i = 0; i < genericArgs.Length; i++)
            {
                var isReadonly = executeMethodParameters[i].GetCustomAttribute(typeof(ReadOnlyAttribute)) != null;
                var type       = new ComponentType(genericArgs[i],
                                                   isReadonly ? ComponentType.AccessMode.ReadOnly : ComponentType.AccessMode.ReadWrite);
                componentTypes.Add(type);

                var isChangedFilter = executeMethodParameters[i].GetCustomAttribute(typeof(ChangedFilterAttribute)) !=
                                      null;
                if (isChangedFilter)
                {
                    changedFilterTypes.Add(type);
                }
            }

            var subtractive = jobType.GetCustomAttribute <RequireSubtractiveComponentAttribute>();

            if (subtractive != null)
            {
                foreach (var type in subtractive.SubtractiveComponents)
                {
                    componentTypes.Add(ComponentType.Subtractive(type));
                }
            }

            var requiredTags = jobType.GetCustomAttribute <RequireComponentTagAttribute>();

            if (requiredTags != null)
            {
                foreach (var type in requiredTags.TagComponents)
                {
                    componentTypes.Add(ComponentType.ReadOnly(type));
                }
            }

            processCount  = genericArgs.Length;
            changedFilter = changedFilterTypes.ToArray();
            return(componentTypes.ToArray());
        }
        private static unsafe ComponentType[] GetComponentTypes(Type jobType, Type interfaceType, out int processCount, out ComponentType[] changedFilter)
        {
            Type[]               genericArguments = interfaceType.GetGenericArguments();
            ParameterInfo[]      parameters       = jobType.GetMethod("Execute").GetParameters();
            List <ComponentType> list             = new List <ComponentType>();
            List <ComponentType> list2            = new List <ComponentType>();
            int num   = (genericArguments.Length != parameters.Length) ? 2 : 0;
            int index = 0;

            while (true)
            {
                ComponentType type;
                if (index >= genericArguments.Length)
                {
                    RequireSubtractiveComponentAttribute customAttribute = jobType.GetCustomAttribute <RequireSubtractiveComponentAttribute>();
                    if (customAttribute != null)
                    {
                        foreach (Type type2 in customAttribute.SubtractiveComponents)
                        {
                            list.Add(ComponentType.Subtractive(type2));
                        }
                    }
                    RequireComponentTagAttribute attribute2 = jobType.GetCustomAttribute <RequireComponentTagAttribute>();
                    if (attribute2 != null)
                    {
                        foreach (Type type3 in attribute2.TagComponents)
                        {
                            list.Add(ComponentType.ReadOnly(type3));
                        }
                    }
                    processCount  = genericArguments.Length;
                    changedFilter = list2.ToArray();
                    return(list.ToArray());
                }
                bool           flag     = parameters[index + num].GetCustomAttribute(typeof(ReadOnlyAttribute)) != null;
                ComponentType *typePtr1 = (ComponentType *)new ComponentType(genericArguments[index], flag ? ComponentType.AccessMode.ReadOnly : ComponentType.AccessMode.ReadWrite);
                typePtr1 = (ComponentType *)ref type;
                list.Add(type);
                if (parameters[index + num].GetCustomAttribute(typeof(ChangedFilterAttribute)) != null)
                {
                    list2.Add(type);
                }
                index++;
            }
        }
Exemplo n.º 5
0
        static ComponentType[] GetComponentTypes(Type jobType, Type interfaceType, out int processCount)
        {
            var genericArgs = interfaceType.GetGenericArguments();

            var executeMethodParameters = jobType.GetMethod("Execute").GetParameters();

            var componentTypes = new List <ComponentType>();

            for (var i = 0; i < genericArgs.Length; i++)
            {
                var isReadonly = executeMethodParameters[i].GetCustomAttribute(typeof(Unity.Collections.ReadOnlyAttribute)) != null ||
                                 executeMethodParameters[i].GetCustomAttribute(typeof(System.Runtime.CompilerServices.IsReadOnlyAttribute)) != null;
                componentTypes.Add(new ComponentType(genericArgs[i], isReadonly ? ComponentType.AccessMode.ReadOnly : ComponentType.AccessMode.ReadWrite));
            }

            var subtractive = jobType.GetCustomAttribute <RequireSubtractiveComponentAttribute>();

            if (subtractive != null)
            {
                foreach (var type in subtractive.SubtractiveComponents)
                {
                    componentTypes.Add(ComponentType.Subtractive(type));
                }
            }

            var requiredTags = jobType.GetCustomAttribute <RequireComponentTagAttribute>();

            if (requiredTags != null)
            {
                //@TODO: Add Special component type which doesn't capture job dependencies...
                foreach (var type in requiredTags.TagComponents)
                {
                    componentTypes.Add(ComponentType.ReadOnly(type));
                }
            }

            processCount = genericArgs.Length;
            return(componentTypes.ToArray());
        }
Exemplo n.º 6
0
        /// <summary>
        ///     Gets array of all ComponentTypes in this ComponentGroup's ArchetypeQueries.
        /// </summary>
        /// <returns>Array of ComponentTypes</returns>
        internal ComponentType[] GetQueryTypes()
        {
#if !UNITY_CSHARP_TINY
            var types = new HashSet <ComponentType>();
#else
            var types = new SlowListSet <ComponentType>();
#endif

            for (var i = 0; i < m_GroupData->ArchetypeQueryCount; ++i)
            {
                for (var j = 0; j < m_GroupData->ArchetypeQuery[i].AnyCount; ++j)
                {
                    types.Add(TypeManager.GetType(m_GroupData->ArchetypeQuery[i].Any[j]));
                }
                for (var j = 0; j < m_GroupData->ArchetypeQuery[i].AllCount; ++j)
                {
                    types.Add(TypeManager.GetType(m_GroupData->ArchetypeQuery[i].All[j]));
                }
                for (var j = 0; j < m_GroupData->ArchetypeQuery[i].NoneCount; ++j)
                {
                    types.Add(ComponentType.Subtractive(TypeManager.GetType(m_GroupData->ArchetypeQuery[i].None[j])));
                }
            }

#if !UNITY_CSHARP_TINY
            var array = new ComponentType[types.Count];
            var t     = 0;
            foreach (var type in types)
            {
                array[t++] = type;
            }
            return(array);
#else
            return(types.ToArray());
#endif
        }
        public ComponentGroupArrayStaticCache(Type type, EntityManager entityManager, ComponentSystemBase system)
        {
            var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            var componentFieldOffsetsBuilder = new List <int>();
            var componentTypesBuilder        = new List <ComponentType>();

            var componentDataFieldOffsetsBuilder = new List <int>();
            var componentDataTypesBuilder        = new List <ComponentType>();

            var subtractiveComponentTypesBuilder = new List <ComponentType>();

            foreach (var field in fields)
            {
                var fieldType = field.FieldType;
                var offset    = UnsafeUtility.GetFieldOffset(field);

                if (fieldType.IsPointer)
                {
                    var isReadOnly = field.GetCustomAttributes(typeof(ReadOnlyAttribute), true).Length != 0;
                    var accessMode =
                        isReadOnly ? ComponentType.AccessMode.ReadOnly : ComponentType.AccessMode.ReadWrite;

                    var elementType = fieldType.GetElementType();

#if ENABLE_UNITY_COLLECTIONS_CHECKS
                    if (!typeof(IComponentData).IsAssignableFrom(elementType) && elementType != typeof(Entity))
                    {
                        throw new ArgumentException(
                                  $"{type}.{field.Name} is a pointer type but not a IComponentData. Only IComponentData or Entity may be a pointer type for enumeration.");
                    }
#endif
                    componentDataFieldOffsetsBuilder.Add(offset);
                    componentDataTypesBuilder.Add(new ComponentType(elementType, accessMode));
                }
                else if (TypeManager.UnityEngineComponentType?.IsAssignableFrom(fieldType) ?? false)
                {
                    componentFieldOffsetsBuilder.Add(offset);
                    componentTypesBuilder.Add(fieldType);
                }
                else if (fieldType.IsGenericType &&
                         fieldType.GetGenericTypeDefinition() == typeof(SubtractiveComponent <>))
                {
                    subtractiveComponentTypesBuilder.Add(ComponentType.Subtractive(fieldType.GetGenericArguments()[0]));
                }
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                else if (typeof(IComponentData).IsAssignableFrom(fieldType))
                {
                    throw new ArgumentException(
                              $"{type}.{field.Name} must be an unsafe pointer to the {fieldType}. Like this: {fieldType}* {field.Name};");
                }
                else
                {
                    throw new ArgumentException($"{type}.{field.Name} can not be used in a component enumerator");
                }
#endif
            }
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            if (componentTypesBuilder.Count + componentDataTypesBuilder.Count > ComponentGroupArrayData.kMaxStream)
            {
                throw new ArgumentException(
                          $"{type} has too many component references. A ComponentGroup Array can have up to {ComponentGroupArrayData.kMaxStream}.");
            }
#endif

            ComponentDataCount = componentDataTypesBuilder.Count;
            ComponentCount     = componentTypesBuilder.Count;

            componentDataTypesBuilder.AddRange(componentTypesBuilder);
            componentDataTypesBuilder.AddRange(subtractiveComponentTypesBuilder);
            ComponentTypes = componentDataTypesBuilder.ToArray();

            componentDataFieldOffsetsBuilder.AddRange(componentFieldOffsetsBuilder);
            ComponentFieldOffsets = componentDataFieldOffsetsBuilder.ToArray();

            ComponentGroup = system.GetComponentGroupInternal(ComponentTypes);
            SafetyManager  = entityManager.ComponentJobSafetyManager;

            CachedType = type;
        }
        private static string CollectInjectedGroup(ComponentSystemBase system, FieldInfo groupField,
                                                   Type injectedGroupType, out FieldInfo entityArrayField, out FieldInfo indexFromEntityField,
                                                   InjectionContext injectionContext, out FieldInfo lengthField, out FieldInfo componentGroupIndexField,
                                                   ISet <ComponentType> componentRequirements, ICollection <InjectionData> componentDataInjections,
                                                   ICollection <InjectionData> bufferDataInjections, ICollection <InjectionData> sharedComponentInjections)
        {
            //@TODO: Improve error messages...
            var fields =
                injectedGroupType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            entityArrayField         = null;
            indexFromEntityField     = null;
            lengthField              = null;
            componentGroupIndexField = null;

            foreach (var field in fields)
            {
                var isReadOnly = field.GetCustomAttributes(typeof(ReadOnlyAttribute), true).Length != 0;
                //@TODO: Prevent using GameObjectEntity, it will never show up. Point to GameObjectArray instead...

                if (field.FieldType.IsGenericType &&
                    field.FieldType.GetGenericTypeDefinition() == typeof(ComponentDataArray <>))
                {
                    var injection = new InjectionData(field, field.FieldType.GetGenericArguments()[0], isReadOnly);
                    componentDataInjections.Add(injection);
                    componentRequirements.Add(injection.ComponentType);
                }
                else if (field.FieldType.IsGenericType &&
                         field.FieldType.GetGenericTypeDefinition() == typeof(SubtractiveComponent <>))
                {
                    componentRequirements.Add(ComponentType.Subtractive(field.FieldType.GetGenericArguments()[0]));
                }
                else if (field.FieldType.IsGenericType &&
                         field.FieldType.GetGenericTypeDefinition() == typeof(BufferArray <>))
                {
                    var injection = new InjectionData(field, field.FieldType.GetGenericArguments()[0], isReadOnly);

                    bufferDataInjections.Add(injection);
                    componentRequirements.Add(injection.ComponentType);
                }
                else if (field.FieldType.IsGenericType &&
                         field.FieldType.GetGenericTypeDefinition() == typeof(SharedComponentDataArray <>))
                {
                    if (!isReadOnly)
                    {
                        return
                            ($"{system.GetType().Name}:{groupField.Name} SharedComponentDataArray<> must always be injected as [ReadOnly]");
                    }
                    var injection = new InjectionData(field, field.FieldType.GetGenericArguments()[0], true);

                    sharedComponentInjections.Add(injection);
                    componentRequirements.Add(injection.ComponentType);
                }
                else if (field.FieldType == typeof(EntityArray))
                {
                    // Error on multiple EntityArray
                    if (entityArrayField != null)
                    {
                        return
                            ($"{system.GetType().Name}:{groupField.Name} An [Inject] struct, may only contain a single EntityArray");
                    }

                    entityArrayField = field;
                }
                else if (field.FieldType == typeof(int))
                {
                    if (field.Name != "Length" && field.Name != "GroupIndex")
                    {
                        return
                            ($"{system.GetType().Name}:{groupField.Name} Int in an [Inject] struct should be named \"Length\" (group length) or \"GroupIndex\" (index in ComponentGroup[])");
                    }

                    if (!field.IsInitOnly)
                    {
                        return
                            ($"{system.GetType().Name}:{groupField.Name} {field.Name} must use the \"readonly\" keyword");
                    }

                    if (field.Name == "Length")
                    {
                        lengthField = field;
                    }

                    if (field.Name == "GroupIndex")
                    {
                        componentGroupIndexField = field;
                    }
                }
                else
                {
                    var hook = InjectionHookSupport.HookFor(field);
                    if (hook == null)
                    {
                        return
                            ($"{system.GetType().Name}:{groupField.Name} [Inject] may only be used on ComponentDataArray<>, ComponentArray<>, TransformAccessArray, EntityArray, {string.Join(",", InjectionHookSupport.Hooks.Select(h => h.FieldTypeOfInterest.Name))} and int Length.");
                    }

                    var error = hook.ValidateField(field, isReadOnly, injectionContext);
                    if (error != null)
                    {
                        return(error);
                    }

                    injectionContext.AddEntry(hook.CreateInjectionInfoFor(field, isReadOnly));
                }
            }

            if (injectionContext.HasComponentRequirements)
            {
                foreach (var requirement in injectionContext.ComponentRequirements)
                {
                    componentRequirements.Add(requirement);
                }
            }

            return(null);
        }
        static string CollectInjectedGroup(Type injectedGroupType, out FieldInfo entityArrayField, out FieldInfo indexFromEntityField, InjectionContext injectionContext, out FieldInfo lengthField, ISet <ComponentType> componentRequirements,
                                           ICollection <InjectionData> componentDataInjections, ICollection <InjectionData> fixedArrayInjections, ICollection <InjectionData> sharedComponentInjections)
        {
            //@TODO: Improve error messages...
            var fields = injectedGroupType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            entityArrayField     = null;
            indexFromEntityField = null;
            lengthField          = null;

            foreach (var field in fields)
            {
                var isReadOnly = field.GetCustomAttributes(typeof(ReadOnlyAttribute), true).Length != 0;
                //@TODO: Prevent using GameObjectEntity, it will never show up. Point to GameObjectArray instead...

                if (field.FieldType.IsGenericType && field.FieldType.GetGenericTypeDefinition() == typeof(ComponentDataArray <>))
                {
                    var injection = new InjectionData(field, field.FieldType.GetGenericArguments()[0], isReadOnly);
                    componentDataInjections.Add(injection);
                    componentRequirements.Add(injection.ComponentType);
                }
                else if (field.FieldType.IsGenericType && field.FieldType.GetGenericTypeDefinition() == typeof(SubtractiveComponent <>))
                {
                    componentRequirements.Add(ComponentType.Subtractive(field.FieldType.GetGenericArguments()[0]));
                }
                else if (field.FieldType.IsGenericType && field.FieldType.GetGenericTypeDefinition() == typeof(FixedArrayArray <>))
                {
                    var injection = new InjectionData(field, field.FieldType.GetGenericArguments()[0], isReadOnly);

                    fixedArrayInjections.Add(injection);
                    componentRequirements.Add(injection.ComponentType);
                }
                else if (field.FieldType.IsGenericType && field.FieldType.GetGenericTypeDefinition() == typeof(SharedComponentDataArray <>))
                {
                    if (!isReadOnly)
                    {
                        return("SharedComponentDataArray<> must always be injected as [ReadOnly]");
                    }
                    var injection = new InjectionData(field, field.FieldType.GetGenericArguments()[0], true);

                    sharedComponentInjections.Add(injection);
                    componentRequirements.Add(injection.ComponentType);
                }
                else if (field.FieldType == typeof(EntityArray))
                {
                    // Error on multiple EntityArray
                    if (entityArrayField != null)
                    {
                        return("A [Inject] struct, may only contain a single EntityArray");
                    }

                    entityArrayField = field;
                }
                else if (field.FieldType == typeof(IndexFromEntity))
                {
                    // Error on multiple IndexFromEntity
                    if (indexFromEntityField != null)
                    {
                        return("A [Inject] struct, may only contain a single IndexFromEntity");
                    }

                    indexFromEntityField = field;
                }
                else if (field.FieldType == typeof(int))
                {
                    // Error on multiple EntityArray
                    if (field.Name != "Length")
                    {
                        return("A [Inject] struct, supports only a specialized int storing the length of the group. (\"int Length;\")");
                    }
                    lengthField = field;
                }
                else
                {
                    var hook = InjectionHookSupport.HookFor(field);
                    if (hook == null)
                    {
                        return
                            ($"[Inject] may only be used on ComponentDataArray<>, ComponentArray<>, TransformAccessArray, EntityArray, {string.Join(",", InjectionHookSupport.Hooks.Select(h => h.FieldTypeOfInterest.Name))} and int Length.");
                    }

                    var error = hook.ValidateField(field, isReadOnly, injectionContext);
                    if (error != null)
                    {
                        return(error);
                    }

                    injectionContext.AddEntry(hook.CreateInjectionInfoFor(field, isReadOnly));
                }
            }

            if (injectionContext.HasComponentRequirements)
            {
                foreach (var requirement in injectionContext.ComponentRequirements)
                {
                    componentRequirements.Add(requirement);
                }
            }

            return(null);
        }
Exemplo n.º 10
0
        public ComponentGroupArrayStaticCache(Type type, EntityManager entityManager, ComponentSystemBase system)
        {
            List <int>           collection = new List <int>();
            List <ComponentType> list2      = new List <ComponentType>();
            List <int>           list3      = new List <int>();
            List <ComponentType> list4      = new List <ComponentType>();
            List <ComponentType> list5      = new List <ComponentType>();

            foreach (FieldInfo info in type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
            {
                Type fieldType   = info.FieldType;
                int  fieldOffset = UnsafeUtility.GetFieldOffset(info);
                if (fieldType.IsPointer)
                {
                    ComponentType.AccessMode accessModeType = (info.GetCustomAttributes(typeof(ReadOnlyAttribute), true).Length != 0) ? ComponentType.AccessMode.ReadOnly : ComponentType.AccessMode.ReadWrite;
                    Type elementType = fieldType.GetElementType();
                    if (!typeof(IComponentData).IsAssignableFrom(elementType) && (elementType != typeof(Entity)))
                    {
                        throw new ArgumentException($"{type}.{info.Name} is a pointer type but not a IComponentData. Only IComponentData or Entity may be a pointer type for enumeration.");
                    }
                    list3.Add(fieldOffset);
                    list4.Add(new ComponentType(elementType, accessModeType));
                }
                else
                {
                    bool flag1;
                    if (TypeManager.UnityEngineComponentType != null)
                    {
                        flag1 = TypeManager.UnityEngineComponentType.IsAssignableFrom(fieldType);
                    }
                    else
                    {
                        object unityEngineComponentType = TypeManager.UnityEngineComponentType;
                        flag1 = false;
                    }
                    if (flag1)
                    {
                        collection.Add(fieldOffset);
                        list2.Add(fieldType);
                    }
                    else
                    {
                        if (!(fieldType.IsGenericType && (fieldType.GetGenericTypeDefinition() == typeof(SubtractiveComponent <>))))
                        {
                            if (!typeof(IComponentData).IsAssignableFrom(fieldType))
                            {
                                throw new ArgumentException($"{type}.{info.Name} can not be used in a component enumerator");
                            }
                            throw new ArgumentException($"{type}.{info.Name} must be an unsafe pointer to the {fieldType}. Like this: {fieldType}* {info.Name};");
                        }
                        list5.Add(ComponentType.Subtractive(fieldType.GetGenericArguments()[0]));
                    }
                }
            }
            if ((list2.Count + list4.Count) > 6)
            {
                throw new ArgumentException($"{type} has too many component references. A ComponentGroup Array can have up to {6}.");
            }
            this.ComponentDataCount = list4.Count;
            this.ComponentCount     = list2.Count;
            list4.AddRange(list2);
            list4.AddRange(list5);
            this.ComponentTypes = list4.ToArray();
            list3.AddRange(collection);
            this.ComponentFieldOffsets = list3.ToArray();
            this.ComponentGroup        = system.GetComponentGroupInternal(this.ComponentTypes);
            this.SafetyManager         = entityManager.ComponentJobSafetyManager;
            this.CachedType            = type;
        }
        private static string CollectInjectedGroup(ComponentSystemBase system, FieldInfo groupField, Type injectedGroupType, out FieldInfo entityArrayField, out FieldInfo indexFromEntityField, InjectionContext injectionContext, out FieldInfo lengthField, out FieldInfo componentGroupIndexField, ISet <ComponentType> componentRequirements, ICollection <InjectionData> componentDataInjections, ICollection <InjectionData> bufferDataInjections, ICollection <InjectionData> sharedComponentInjections)
        {
            string str;

            FieldInfo[] fields = injectedGroupType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
            entityArrayField         = null;
            indexFromEntityField     = null;
            lengthField              = null;
            componentGroupIndexField = null;
            FieldInfo[] infoArray2 = fields;
            int         index      = 0;

            while (true)
            {
                if (index >= infoArray2.Length)
                {
                    if (injectionContext.HasComponentRequirements)
                    {
                        foreach (ComponentType type in injectionContext.ComponentRequirements)
                        {
                            componentRequirements.Add(type);
                        }
                    }
                    str = null;
                    break;
                }
                FieldInfo field      = infoArray2[index];
                bool      isReadOnly = field.GetCustomAttributes(typeof(ReadOnlyAttribute), true).Length != 0;
                if (field.FieldType.IsGenericType && (field.FieldType.GetGenericTypeDefinition() == typeof(ComponentDataArray <>)))
                {
                    InjectionData item = new InjectionData(field, field.FieldType.GetGenericArguments()[0], isReadOnly);
                    componentDataInjections.Add(item);
                    componentRequirements.Add(item.ComponentType);
                }
                else if (field.FieldType.IsGenericType && (field.FieldType.GetGenericTypeDefinition() == typeof(SubtractiveComponent <>)))
                {
                    componentRequirements.Add(ComponentType.Subtractive(field.FieldType.GetGenericArguments()[0]));
                }
                else if (field.FieldType.IsGenericType && (field.FieldType.GetGenericTypeDefinition() == typeof(BufferArray <>)))
                {
                    InjectionData item = new InjectionData(field, field.FieldType.GetGenericArguments()[0], isReadOnly);
                    bufferDataInjections.Add(item);
                    componentRequirements.Add(item.ComponentType);
                }
                else if (field.FieldType.IsGenericType && (field.FieldType.GetGenericTypeDefinition() == typeof(SharedComponentDataArray <>)))
                {
                    if (!isReadOnly)
                    {
                        str = $"{system.GetType().Name}:{groupField.Name} SharedComponentDataArray<> must always be injected as [ReadOnly]";
                        break;
                    }
                    InjectionData item = new InjectionData(field, field.FieldType.GetGenericArguments()[0], true);
                    sharedComponentInjections.Add(item);
                    componentRequirements.Add(item.ComponentType);
                }
                else if (field.FieldType == typeof(EntityArray))
                {
                    if (entityArrayField != null)
                    {
                        str = $"{system.GetType().Name}:{groupField.Name} An [Inject] struct, may only contain a single EntityArray";
                        break;
                    }
                    entityArrayField = field;
                }
                else if (!(field.FieldType == typeof(int)))
                {
                    InjectionHook hook = InjectionHookSupport.HookFor(field);
                    if (hook == null)
                    {
                        str = $"{system.GetType().Name}:{groupField.Name} [Inject] may only be used on ComponentDataArray<>, ComponentArray<>, TransformAccessArray, EntityArray, {string.Join(",", (IEnumerable<string>) (from h in InjectionHookSupport.Hooks select h.FieldTypeOfInterest.Name))} and int Length.";
                        break;
                    }
                    string str2 = hook.ValidateField(field, isReadOnly, injectionContext);
                    if (str2 != null)
                    {
                        str = str2;
                        break;
                    }
                    injectionContext.AddEntry(hook.CreateInjectionInfoFor(field, isReadOnly));
                }
                else
                {
                    if ((field.Name != "Length") && (field.Name != "GroupIndex"))
                    {
                        str = $"{system.GetType().Name}:{groupField.Name} Int in an [Inject] struct should be named " Length " (group length) or " GroupIndex " (index in ComponentGroup[])";
                        break;
                    }
                    if (!field.IsInitOnly)
                    {
                        str = $"{system.GetType().Name}:{groupField.Name} {field.Name} must use the " readonly " keyword";