Beispiel #1
0
        /// <summary>
        /// Note: unluckily I didn't design the serialization system to be component order independent, so unless
        /// I do something about it, this method cannot be optimized, the logic of the component order must stay
        /// untouched (no reordering, no use of dictionaries). Components order must stay as it comes, as
        /// well as extracomponents order.
        /// Speed, however, is not a big issue for this class, as the data is always composed once per entity descriptor
        /// at static constructor time
        /// </summary>
        /// <returns></returns>
        IComponentBuilder[] Construct(int extraComponentsLength, IComponentBuilder[] extraComponents)
        {
            IComponentBuilder[] MergeLists
                (IComponentBuilder[] startingComponents, IComponentBuilder[] newComponents, int newComponentsLength)
            {
                var startComponents =
                    new FasterDictionary <RefWrapper <IComponentBuilder, ComponentBuilderComparer>, IComponentBuilder>();
                var xtraComponents =
                    new FasterDictionary <RefWrapper <IComponentBuilder, ComponentBuilderComparer>, IComponentBuilder>();

                for (uint i = 0; i < startingComponents.Length; i++)
                {
                    startComponents
                    [new RefWrapper <IComponentBuilder, ComponentBuilderComparer>(startingComponents[i])] =
                        startingComponents[i];
                }

                for (uint i = 0; i < newComponentsLength; i++)
                {
                    xtraComponents[new RefWrapper <IComponentBuilder, ComponentBuilderComparer>(newComponents[i])] =
                        newComponents[i];
                }

                xtraComponents.Exclude(startComponents);

                if (newComponentsLength != xtraComponents.count)
                {
                    newComponentsLength = xtraComponents.count;

                    uint index = 0;
                    foreach (var couple in xtraComponents)
                    {
                        newComponents[index++] = couple.key.type;
                    }
                }

                IComponentBuilder[] componentBuilders =
                    new IComponentBuilder[newComponentsLength + startingComponents.Length];

                Array.Copy(startingComponents, 0, componentBuilders, 0, startingComponents.Length);
                Array.Copy(newComponents, 0, componentBuilders, startingComponents.Length, newComponentsLength);

                var entityInfoComponentIndex = FetchEntityInfoComponent(componentBuilders);

                DBC.ECS.Check.Assert(entityInfoComponentIndex != -1);

                componentBuilders[entityInfoComponentIndex] = new ComponentBuilder <EntityInfoComponent>(
                    new EntityInfoComponent
                {
                    componentsToBuild = componentBuilders
                });

                return(componentBuilders);
            }

            if (extraComponentsLength == 0)
            {
                return(_componentsToBuild);
            }

            var safeCopyOfExtraComponents = new IComponentBuilder[extraComponentsLength];

            Array.Copy(extraComponents, safeCopyOfExtraComponents, extraComponentsLength);

            return(MergeLists(_componentsToBuild, safeCopyOfExtraComponents, extraComponentsLength));
        }
        internal static void SetEntityViewComponentImplementors <T>(this IComponentBuilder componentBuilder,
                                                                    ref T entityComponent, IEnumerable <object> implementors,
                                                                    ComponentBuilder <T> .EntityViewComponentCache localCache) where T : struct, IBaseEntityComponent
        {
            DBC.ECS.Check.Require(implementors != null,
                                  NULL_IMPLEMENTOR_ERROR.FastConcat(" entityComponent ",
                                                                    componentBuilder.GetEntityComponentType().ToString()));

            var cachedTypeInterfaces = localCache.cachedTypes;
            var implementorsByType   = localCache.implementorsByType;
            var entityComponentBlazingFastReflection = localCache.cachedFields;

            foreach (var implementor in implementors)
            {
                DBC.ECS.Check.Require(implementor != null, "invalid null implementor used to build an entity");
                {
                    var type = implementor.GetType();

                    //fetch all the interfaces that the implementor implements
                    if (cachedTypeInterfaces.TryGetValue(type, out var interfaces) == false)
                    {
                        interfaces = cachedTypeInterfaces[type] = type.GetInterfacesEx();
                    }

                    for (var iindex = 0; iindex < interfaces.Length; iindex++)
                    {
                        var componentType = interfaces[iindex];
                        //an implementor can implement multiple interfaces, so for each interface we reference
                        //the implementation object. Multiple entity view component fields can then be implemented
                        //by the same implementor
#if DEBUG && !PROFILE_SVELTO
                        if (implementorsByType.TryGetValue(componentType, out var implementorData))
                        {
                            implementorData.numberOfImplementations++;
                            implementorsByType[componentType] = implementorData;
                        }
                        else
                        {
                            implementorsByType[componentType] = new ECSTuple <object, int>(implementor, 1);
                        }
#else
                        implementorsByType[componentType] = implementor;
#endif
                    }
                }
            }

            //efficient way to collect the fields of every EntityComponentType
            var setters = FasterList <KeyValuePair <Type, FastInvokeActionCast <T> > > .NoVirt.ToArrayFast(
                entityComponentBlazingFastReflection, out var count);

            for (var i = 0; i < count; i++)
            {
                var fieldSetter = setters[i];
                var fieldType   = fieldSetter.Key;

#if DEBUG && !PROFILE_SVELTO
                ECSTuple <object, int> implementor;
#else
                object implementor;
#endif

                if (implementorsByType.TryGetValue(fieldType, out implementor) == false)
                {
                    var e = new ECSException(NOT_FOUND_EXCEPTION + " Component Type: " + fieldType.Name +
                                             " - EntityComponent: " + componentBuilder.GetEntityComponentType().Name);

                    throw e;
                }
#if DEBUG && !PROFILE_SVELTO
                if (implementor.numberOfImplementations > 1)
                {
                    throw new ECSException(DUPLICATE_IMPLEMENTOR_ERROR.FastConcat(
                                               "Component Type: ", fieldType.Name, " implementor: ", implementor.instance.ToString()) +
                                           " - EntityComponent: " + componentBuilder.GetEntityComponentType().Name);
                }
#endif
#if DEBUG && !PROFILE_SVELTO
                fieldSetter.Value(ref entityComponent, implementor.instance);
#else
                fieldSetter.Value(ref entityComponent, implementor);
#endif
            }

            implementorsByType.Clear();
        }