Exemple #1
0
        /// <summary>
        /// Add and remove multiple component to an entity
        /// </summary>
        /// <param name="entityHandle"></param>
        /// <param name="componentType"></param>
        /// <returns></returns>
        public void AddRemoveMultipleComponent(GameEntityHandle entityHandle, Span <ComponentType> addSpan, Span <ComponentType> removeSpan)
        {
            ThrowOnInvalidHandle(entityHandle);

            var updateArch = false;

            foreach (ref readonly var componentType in addSpan)
            {
                var componentBoard = GameWorldLL.GetComponentBoardBase(Boards.ComponentType, componentType);
                var cRef           = new ComponentReference(componentType, GameWorldLL.CreateComponent(componentBoard));

                updateArch |= GameWorldLL.AssignComponent(componentBoard, cRef, Boards.Entity, entityHandle);
                GameWorldLL.SetOwner(componentBoard, cRef, entityHandle);
            }

            foreach (ref readonly var componentType in removeSpan)
            {
                updateArch |= GameWorldLL.RemoveComponentReference(GameWorldLL.GetComponentBoardBase(Boards.ComponentType, componentType), componentType, Boards.Entity, entityHandle);
            }

            if (updateArch)
            {
                GameWorldLL.UpdateArchetype(Boards.Archetype, Boards.ComponentType, Boards.Entity, entityHandle);
            }
        }
        /// <summary>
        /// Get the reference to a component data from an entity
        /// </summary>
        /// <param name="entityHandle"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public ref T GetComponentData <T>(GameEntityHandle entityHandle)
            where T : struct, IComponentData
        {
            ThrowOnInvalidHandle(entityHandle);

            var componentType = AsComponentType <T>().Id;
            var board         = Boards.ComponentType.ComponentBoardColumns[(int)componentType];

            if (board is TagComponentBoard)
            {
                return(ref TagComponentBoard.Default <T> .V);
            }

            if (!(board is SingleComponentBoard componentColumn))
            {
                throw new InvalidOperationException($"A board made from an {nameof(IComponentData)} should be a {nameof(SingleComponentBoard)}");
            }

#if DEBUG
            if (!HasComponent(entityHandle, new ComponentType(componentType)))
            {
                var msg           = $"{Safe(entityHandle)} has no {Boards.ComponentType.NameColumns[(int) componentType]}. Existing:\n";
                var componentList = Boards.Archetype.GetComponentTypes(GetArchetype(entityHandle).Id);
                foreach (var comp in componentList)
                {
                    msg += $"  [{comp}] {Boards.ComponentType.NameColumns[(int) comp]}\n";
                }

                throw new InvalidOperationException(msg);
            }
#endif

            return(ref componentColumn.AsSpan <T>()[Boards.Entity.GetComponentColumn(componentType)[(int)entityHandle.Id].Assigned]);
Exemple #3
0
        public ComponentReference Copy(GameEntityHandle from, GameEntityHandle to, ComponentType componentType)
        {
            ThrowOnInvalidHandle(from);
            ThrowOnInvalidHandle(to);

            if (!HasComponent(from, componentType))
            {
                throw new InvalidOperationException();
            }

            var fromMetadata   = GetComponentMetadata(from, componentType);
            var toRef          = AddComponent(to, componentType);
            var componentBoard = GameWorldLL.GetComponentBoardBase(Boards.ComponentType, componentType);

            switch (componentBoard)
            {
            case SingleComponentBoard singleComponentBoard:
                singleComponentBoard.ReadRaw(fromMetadata.Id)
                .CopyTo(singleComponentBoard.ReadRaw(toRef.Id));
                break;

            case BufferComponentBoard bufferComponentBoard:
            {
                var toBuffer = bufferComponentBoard.AsSpan()[(int)toRef.Id];
                toBuffer.Clear();
                toBuffer.AddRange(bufferComponentBoard.AsSpan()[(int)fromMetadata.Id]);
                break;
            }
            }

            return(toRef);
        }
        public GameEntityHandle CreateEntity()
        {
            var handle = new GameEntityHandle(Boards.Entity.CreateRow());

            GameWorldLL.UpdateArchetype(Boards.Archetype, Boards.ComponentType, Boards.Entity, handle);
            return(handle);
        }
Exemple #5
0
        /// <summary>
        /// Assure that an entity has the components. If an entity already possess one of them, it will not get replaced.
        /// </summary>
        /// <param name="entityHandle"></param>
        /// <param name="componentTypeSpan"></param>
        public void AssureComponents(GameEntityHandle entityHandle, Span <ComponentType> componentTypeSpan)
        {
            var updateArchetype = false;
            var entityBoard     = Boards.Entity;

            foreach (ref readonly var componentType in componentTypeSpan)
            {
                // TODO: support for shared component
                if (entityBoard.GetComponentColumn(componentType.Id)[(int)entityHandle.Id].Valid)
                {
                    continue;
                }

                var componentBoard = GameWorldLL.GetComponentBoardBase(Boards.ComponentType, componentType);
                var cRef           = new ComponentReference(componentType, GameWorldLL.CreateComponent(componentBoard));

                GameWorldLL.AssignComponent(componentBoard, cRef, Boards.Entity, entityHandle);
                GameWorldLL.SetOwner(componentBoard, cRef, entityHandle);

                updateArchetype = true;
            }

            if (updateArchetype)
            {
                GameWorldLL.UpdateArchetype(Boards.Archetype, Boards.ComponentType, Boards.Entity, entityHandle);
            }
        }
        /// <summary>
        /// Set if a child entity should be linked to an owner entity. If the owner get removed, the child will too.
        /// </summary>
        /// <param name="child"></param>
        /// <param name="owner"></param>
        /// <param name="isLinked"></param>
        /// <returns>Return if the linking state has been changed</returns>
        public bool Link(GameEntityHandle child, GameEntityHandle owner, bool isLinked)
        {
            ThrowOnInvalidHandle(child);
            ThrowOnInvalidHandle(owner);

            return(isLinked
                                ? Boards.Entity.AddLinked(owner.Id, child.Id)
                                : Boards.Entity.RemoveLinked(owner.Id, child.Id));
        }
        public GameEntity Safe(GameEntityHandle handle)
        {
            ThrowOnInvalidHandle(handle);

            unchecked
            {
                return(new GameEntity(handle.Id, Boards.Entity.VersionColumn[(int)handle.Id]));
            }
        }
Exemple #8
0
        /// <summary>
        /// Assign an existing component to an entity
        /// </summary>
        /// <param name="entityHandle"></param>
        /// <param name="component"></param>
        public void AssignComponent(GameEntityHandle entityHandle, ComponentReference component)
        {
            ThrowOnInvalidHandle(entityHandle);

            var board = GameWorldLL.GetComponentBoardBase(Boards.ComponentType, component.Type);

            GameWorldLL.AssignComponent(board, component, Boards.Entity, entityHandle);
            GameWorldLL.UpdateArchetype(Boards.Archetype, Boards.ComponentType, Boards.Entity, entityHandle);
        }
        public ComponentReference GetComponentReference <T>(GameEntityHandle entityHandle)
            where T : struct, IEntityComponent
        {
            ThrowOnInvalidHandle(entityHandle);

            var componentType = AsComponentType <T>();

            return(new ComponentReference(componentType, Boards.Entity.GetComponentColumn(componentType.Id)[(int)entityHandle.Id].Id));
        }
 public void ThrowOnInvalidHandle(GameEntityHandle handle)
 {
     if (handle.Id == 0)
     {
         throw new InvalidOperationException("You've passed an invalid handle");
     }
     if (Boards.Entity.ArchetypeColumn[(int)handle.Id].Id == 0)
     {
         throw new InvalidOperationException($"The GameWorld does not contains a handle with id '{handle.Id}'");
     }
 }
Exemple #11
0
        /// <summary>
        /// Remove a component from an entity.
        /// </summary>
        /// <param name="entityHandle">The entity</param>
        /// <param name="componentType">The component type</param>
        /// <returns>True if the component was removed, false if it did not exist.</returns>
        public bool RemoveComponent(GameEntityHandle entityHandle, ComponentType componentType)
        {
            ThrowOnInvalidHandle(entityHandle);

            if (GameWorldLL.RemoveComponentReference(GameWorldLL.GetComponentBoardBase(Boards.ComponentType, componentType), componentType, Boards.Entity, entityHandle))
            {
                GameWorldLL.UpdateArchetype(Boards.Archetype, Boards.ComponentType, Boards.Entity, entityHandle);
                return(true);
            }

            return(false);
        }
Exemple #12
0
        /// <summary>
        /// Add multiple component to an entity
        /// </summary>
        /// <param name="entityHandle"></param>
        /// <param name="componentType"></param>
        /// <remarks>
        ///	If you wish to not replace existing components, use <see cref="AssureComponents"/> (a bit slower than this method)
        /// </remarks>
        public void AddMultipleComponent(GameEntityHandle entityHandle, Span <ComponentType> componentTypeSpan)
        {
            ThrowOnInvalidHandle(entityHandle);

            foreach (ref readonly var componentType in componentTypeSpan)
            {
                var componentBoard = GameWorldLL.GetComponentBoardBase(Boards.ComponentType, componentType);
                var cRef           = new ComponentReference(componentType, GameWorldLL.CreateComponent(componentBoard));

                GameWorldLL.AssignComponent(componentBoard, cRef, Boards.Entity, entityHandle);
                GameWorldLL.SetOwner(componentBoard, cRef, entityHandle);
            }

            GameWorldLL.UpdateArchetype(Boards.Archetype, Boards.ComponentType, Boards.Entity, entityHandle);
        }
        public void RemoveEntity(GameEntityHandle entityHandle)
        {
            ThrowOnInvalidHandle(entityHandle);

            foreach (ref readonly var componentType in Boards.ComponentType.Registered)
            {
                RemoveComponent(entityHandle, componentType);
            }

            var children       = Boards.Entity.GetLinkedEntities(entityHandle.Id);
            var childrenLength = children.Length;

            for (var ent = 0; ent < childrenLength; ent++)
            {
                var linkedEntity = children[ent];
                if (Contains(linkedEntity))
                {
                    RemoveEntity(linkedEntity);
                    ent--;
                    childrenLength--;
                }
            }

            var parents      = Boards.Entity.GetLinkedParents(entityHandle.Id);
            var parentLength = parents.Length;

            for (var ent = 0; ent < parentLength; ent++)
            {
                var parent = parents[ent];
                if (Boards.Entity.RemoveLinked(parent.Id, entityHandle.Id))
                {
                    ent--;
                    parentLength--;
                }
            }

            var archetype = GetArchetype(entityHandle);

            if (archetype.Id > 0)
            {
                Boards.Archetype.RemoveEntity(archetype.Id, entityHandle.Id);
                // Reset archetype of this ID.
                // Since we share the total entity span on clients, the client should know that the entity is deleted via its archetype
                Boards.Entity.ArchetypeColumn[(int)entityHandle.Id] = default;
            }

            Boards.Entity.DeleteRow(entityHandle.Id);
        }
Exemple #14
0
        /// <summary>
        /// Add a component to an entity
        /// </summary>
        /// <param name="entityHandle"></param>
        /// <param name="componentType"></param>
        /// <returns></returns>
        public ComponentReference AddComponent(GameEntityHandle entityHandle, ComponentType componentType)
        {
            ThrowOnInvalidHandle(entityHandle);

            var componentBoard = GameWorldLL.GetComponentBoardBase(Boards.ComponentType, componentType);
            var cRef           = new ComponentReference(componentType, GameWorldLL.CreateComponent(componentBoard));

            GameWorldLL.SetOwner(componentBoard, cRef, entityHandle);
            // Only update archetype if this is a new component to the entity, and not just an update
            if (GameWorldLL.AssignComponent(componentBoard, cRef, Boards.Entity, entityHandle))
            {
                GameWorldLL.UpdateArchetype(Boards.Archetype, Boards.ComponentType, Boards.Entity, entityHandle);
            }

            return(cRef);
        }
Exemple #15
0
        /// <summary>
        /// Remove a component from an entity.
        /// </summary>
        /// <param name="entityHandle">The entity</param>
        /// <param name="componentType">The component type</param>
        /// <returns>True if the component was removed, false if it did not exist.</returns>
        public bool RemoveMultipleComponent(GameEntityHandle entityHandle, Span <ComponentType> componentTypeSpan)
        {
            ThrowOnInvalidHandle(entityHandle);

            var b = true;

            foreach (ref readonly var componentType in componentTypeSpan)
            {
                b &= GameWorldLL.RemoveComponentReference(GameWorldLL.GetComponentBoardBase(Boards.ComponentType, componentType), componentType, Boards.Entity, entityHandle);
            }

            if (b)
            {
                GameWorldLL.UpdateArchetype(Boards.Archetype, Boards.ComponentType, Boards.Entity, entityHandle);
            }

            return(b);
        }
        /// <summary>
        /// Check whether or not an entity has a component
        /// </summary>
        /// <param name="entityHandle"></param>
        /// <param name="componentType"></param>
        /// <returns></returns>
        public bool HasComponent(GameEntityHandle entityHandle, ComponentType componentType)
        {
            var recursionLeft  = RecursionLimit;
            var originalEntity = entityHandle;

            while (recursionLeft-- > 0)
            {
                var link = Boards.Entity.GetComponentColumn(componentType.Id)[(int)entityHandle.Id];
                if (link.IsShared)
                {
                    entityHandle = new GameEntityHandle(link.Entity);
                    continue;
                }

                return(link.Id > 0);
            }

            throw new InvalidOperationException($"HasComponent - Recursion limit reached with '{originalEntity}' and component (backing: {componentType})");
        }
        public void GetComponentOf <TList>(GameEntityHandle entityHandle, ComponentType baseType, TList list)
            where TList : IList <ComponentReference>
        {
            ThrowOnInvalidHandle(entityHandle);

            var archetype = GetArchetype(entityHandle);

            foreach (var componentTypeId in Boards.Archetype.GetComponentTypes(archetype.Id))
            {
                if (Boards.ComponentType.ParentTypeColumns[(int)componentTypeId] != baseType)
                {
                    continue;
                }

                var componentType = new ComponentType(componentTypeId);
                var metadata      = GetComponentMetadata(entityHandle, componentType);
                if (metadata.Null)
                {
                    continue;
                }

                list.Add(new ComponentReference(componentType, metadata.Id));
            }
        }
 public EntityArchetype GetArchetype(GameEntityHandle entityHandle)
 {
     return(Boards.Entity.ArchetypeColumn[(int)entityHandle.Id]);
 }
Exemple #19
0
 /// <summary>
 /// Add a component to an entity
 /// </summary>
 /// <param name="entityHandle"></param>
 /// <param name="data"></param>
 /// <typeparam name="T"></typeparam>
 /// <returns></returns>
 public ComponentReference AddComponent <T>(GameEntityHandle entityHandle, in T data = default)
 /// <summary>
 /// Whether or not this entity handle is valid in the boards.
 /// </summary>
 public bool Contains(GameEntityHandle entityHandle)
 {
     return(entityHandle.Id < Boards.Entity.ArchetypeColumn.Length && Boards.Entity.ArchetypeColumn[(int)entityHandle.Id].Id > 0);
 }
 /// <summary>
 /// Check whether or not an entity has a component
 /// </summary>
 /// <param name="entityHandle"></param>
 /// <typeparam name="T"></typeparam>
 /// <returns></returns>
 public bool HasComponent <T>(GameEntityHandle entityHandle)
     where T : struct, IEntityComponent
 {
     return(HasComponent(entityHandle, AsComponentType <T>()));
 }
        public EntityBoardContainer.ComponentMetadata GetComponentMetadata(GameEntityHandle entityHandle, ComponentType componentType)
        {
            ThrowOnInvalidHandle(entityHandle);

            return(Boards.Entity.GetComponentColumn(componentType.Id)[(int)entityHandle.Id]);
        }