/// <summary>
        /// Update the store with the recorded BlobAsset/UnityObject associations.
        /// </summary>
        /// <remarks>
        /// User don't have to call this method because <see cref="Dispose"/> will do it.
        /// This method can be called multiple times, on the first one will matter.
        /// </remarks>
        public void UpdateBlobStore()
        {
            var keys = m_BlobPerUnityObject.GetUniqueKeyArray(Allocator.Temp);

            using (keys.Item1)
            {
                for (var k = 0; k < keys.Item2; ++k)
                {
                    var key        = keys.Item1[k];
                    var valueCount = m_BlobPerUnityObject.CountValuesForKey(key);
                    var valueArray = new NativeArray <Hash128>(valueCount, Allocator.Temp);
                    var i          = 0;
                    if (m_BlobPerUnityObject.TryGetFirstValue(key, out var value, out var iterator))
                    {
                        do
                        {
                            valueArray[i++] = value;
                        }while (m_BlobPerUnityObject.TryGetNextValue(out value, ref iterator));

                        valueArray.Sort();
                    }

                    m_BlobAssetStore.UpdateBlobAssetForUnityObject <TB>(key, valueArray);
                    valueArray.Dispose();
                }
            }

            m_BlobPerUnityObject.Clear();
        }
예제 #2
0
    public void NativeMultiHashMap_GetKeys()
    {
        var container = new NativeMultiHashMap <int, int>(1, Allocator.Temp);

        for (int i = 0; i < 30; ++i)
        {
            container.Add(i, 2 * i);
            container.Add(i, 3 * i);
        }
        var keys = container.GetKeyArray(Allocator.Temp);

#if !NET_DOTS // Tuple is not supported by TinyBCL
        var(unique, uniqueLength) = container.GetUniqueKeyArray(Allocator.Temp);
        Assert.AreEqual(30, uniqueLength);
#endif

        Assert.AreEqual(60, keys.Length);
        keys.Sort();
        for (int i = 0; i < 30; ++i)
        {
            Assert.AreEqual(i, keys[i * 2 + 0]);
            Assert.AreEqual(i, keys[i * 2 + 1]);
#if !NET_DOTS // Tuple is not supported by TinyBCL
            Assert.AreEqual(i, unique[i]);
#endif
        }
    }
    public void NativeMultiHashMap_GetUniqueKeysEmpty()
    {
        var hashMap = new NativeMultiHashMap <int, int> (1, Allocator.Temp);
        var keys    = hashMap.GetUniqueKeyArray(Allocator.Temp);

        Assert.AreEqual(0, keys.Item1.Length);
        Assert.AreEqual(0, keys.Item2);
    }
예제 #4
0
        protected override void OnUpdate()
        {
            // A map from entities to arrays of colliders that were not applied to the body during the first pass.
            m_ExtraColliders = new NativeMultiHashMap <ComparableEntity, LeafShapeData>(64, Allocator.Temp); // TODO - add custom data to Physics.Collider?

            // First pass.
            // Convert all editor shape components into colliders, and either apply them to their parent rigid body
            // or store them for building compound colliders in the second pass.
            Entities.ForEach <T>(ConvertShape);

            // Second pass.
            // Merge any leftover colliders into their parent rigid bodies, as compound colliders.
            if (m_ExtraColliders.Length > 0)
            {
                var keys = m_ExtraColliders.GetUniqueKeyArray(Allocator.Temp);
                using (keys.Item1)
                {
                    for (var k = 0; k < keys.Item2; ++k)
                    {
                        ComparableEntity entity = keys.Item1[k];
                        var collider            = DstEntityManager.GetComponentData <PhysicsCollider>(entity.Entity);
                        var children            = new NativeList <CompoundCollider.ColliderBlobInstance>(16, Allocator.Temp);

                        if (collider.IsValid)
                        {
                            // Include the already assigned collider as a child
                            children.Add(new CompoundCollider.ColliderBlobInstance {
                                Collider = collider.Value, CompoundFromChild = RigidTransform.identity
                            });
                        }

                        byte customData = 0;
                        if (m_ExtraColliders.TryGetFirstValue(entity, out var child, out var iterator))
                        {
                            do
                            {
                                children.Add(child.ColliderBlobInstance);
                                customData &= child.CustomFlags; // TODO: Should be |= ??
                            } while (m_ExtraColliders.TryGetNextValue(out child, ref iterator));
                        }

                        collider.Value = CompoundCollider.Create(children);

                        children.Dispose();

                        DstEntityManager.SetComponentData(entity.Entity, collider);

                        if (customData != 0)
                        {
                            DstEntityManager.AddOrSetComponent(entity.Entity, new PhysicsCustomData {
                                Value = customData
                            });
                        }
                    }
                }
            }
            m_ExtraColliders.Dispose();
        }
    public void NativeMultiHashMap_GetUniqueKeys()
    {
        var hashMap = new NativeMultiHashMap <int, int> (1, Allocator.Temp);

        for (int i = 0; i < 30; ++i)
        {
            hashMap.Add(i, 2 * i);
            hashMap.Add(i, 3 * i);
        }
        var keys = hashMap.GetUniqueKeyArray(Allocator.Temp);

        hashMap.Dispose();
        Assert.AreEqual(30, keys.Item2);
        for (int i = 0; i < 30; ++i)
        {
            Assert.AreEqual(i, keys.Item1[i]);
        }
        keys.Item1.Dispose();
    }
예제 #6
0
        protected override void OnUpdate()
        {
            var shapeQuery = EntityManager.CreateEntityQuery(ComponentType.ReadOnly <T>());
            var shapeCount = shapeQuery.CalculateEntityCount();

            // A map from entities to arrays of colliders
            m_ExtraColliders = new NativeMultiHashMap <ComparableEntity, LeafShapeData>(shapeCount, Allocator.Temp);

            // Lists to store input data for deferred convex and mesh jobs
            const int defaultPointsPerShape = 1024;

            m_ConvexColliderJobs   = new NativeList <ConvertConvexColliderInput>(shapeCount, Allocator.TempJob);
            m_ConvexColliderPoints = new NativeList <float3>(shapeCount * defaultPointsPerShape, Allocator.TempJob);

            m_MeshColliderJobs     = new NativeList <ConvertMeshColliderInput>(shapeCount, Allocator.TempJob);
            m_MeshColliderVertices = new NativeList <float3>(shapeCount * defaultPointsPerShape, Allocator.TempJob);
            m_MeshColliderIndices  = new NativeList <int>(shapeCount * defaultPointsPerShape / 2, Allocator.TempJob);

            // First pass.
            // Convert all shape authoring components into colliders, and collect them for each primary body
            Entities.ForEach <T>(ConvertShape);

            // Second pass.
            // Produce all convex and mesh collider blobs in parallel
            const int arrayLength     = 5;
            var       convexColliders =
                new NativeArray <KeyValuePair <Entity, LeafShapeData> >(m_ConvexColliderJobs.Length, Allocator.TempJob);
            var convexJob = new ProduceConvexCollidersJob
            {
                InputParameters = m_ConvexColliderJobs,
                AllPoints       = m_ConvexColliderPoints,
                Output          = convexColliders
            }.Schedule(m_ConvexColliderJobs.Length, arrayLength);

            var meshColliders =
                new NativeArray <KeyValuePair <Entity, LeafShapeData> >(m_MeshColliderJobs.Length, Allocator.TempJob);
            var meshJob = new ProduceMeshCollidersJob
            {
                InputParameters = m_MeshColliderJobs,
                AllVertices     = m_MeshColliderVertices,
                AllIndices      = m_MeshColliderIndices,
                Output          = meshColliders
            }.Schedule(m_MeshColliderJobs.Length, arrayLength);

            JobHandle.CombineDependencies(convexJob, meshJob).Complete();

            AppendLeafShapeDataToShapeMap(convexColliders, m_ExtraColliders, m_ConvexShapes);
            convexColliders.Dispose();

            AppendLeafShapeDataToShapeMap(meshColliders, m_ExtraColliders, m_MeshShapes);
            meshColliders.Dispose();

            // Final pass.
            // Assign PhysicsCollider components to rigid bodies, merging multiples into compounds as needed
            var keys = m_ExtraColliders.GetUniqueKeyArray(Allocator.Temp);

            using (keys.Item1)
            {
                for (var k = 0; k < keys.Item2; ++k)
                {
                    ComparableEntity body = keys.Item1[k];
                    var collider          = DstEntityManager.HasComponent <PhysicsCollider>(body.Entity)
                        ? DstEntityManager.GetComponentData <PhysicsCollider>(body.Entity)
                        : new PhysicsCollider();
                    var children = new NativeList <CompoundCollider.ColliderBlobInstance>(16, Allocator.Temp);

                    // collect any existing valid shapes
                    if (collider.IsValid)
                    {
                        ColliderType colliderType;
                        unsafe { colliderType = collider.ColliderPtr->Type; }

                        // if there is already a compound, add its leaves to the list of children
                        if (colliderType == ColliderType.Compound)
                        {
                            unsafe
                            {
                                var existingChildren = ((CompoundCollider *)collider.ColliderPtr)->Children;
                                for (int i = 0, count = existingChildren.Length; i < count; ++i)
                                {
                                    children.Add(new CompoundCollider.ColliderBlobInstance
                                    {
                                        Collider = BlobAssetReference <Collider> .Create(
                                            existingChildren[i].Collider,
                                            existingChildren[i].Collider->MemorySize
                                            ),
                                        CompoundFromChild = existingChildren[i].CompoundFromChild
                                    });
                                }
                            }
                        }
                        // otherwise add the single collider to the list of children
                        else
                        {
                            children.Add(
                                new CompoundCollider.ColliderBlobInstance
                            {
                                Collider          = collider.Value,
                                CompoundFromChild = RigidTransform.identity
                            }
                                );
                        }
                    }

                    // if collider is already valid, a shape already existed from another system
                    var isSingleShapeOnPrimaryBody = !collider.IsValid;
                    // collect all children found by this system
                    if (m_ExtraColliders.TryGetFirstValue(body, out var child, out var iterator))
                    {
                        do
                        {
                            children.Add(child.ColliderBlobInstance);
                            isSingleShapeOnPrimaryBody &= child.LeafEntity.Equals(body.Entity);
                        } while (m_ExtraColliders.TryGetNextValue(out child, ref iterator));
                    }

                    // if there is a single shape on the primary body, use it as-is, otherwise create a compound
                    // (assume a single leaf should still be a compound so that local offset values in authoring representation are retained)
                    collider.Value = isSingleShapeOnPrimaryBody
                        ? children[0].Collider
                        : CompoundCollider.Create(children);

                    children.Dispose();

                    DstEntityManager.AddOrSetComponent(body.Entity, collider);
                }
            }

            m_ConvexShapes.Clear();
            m_ConvexColliderJobs.Dispose();
            m_ConvexColliderPoints.Dispose();

            m_MeshShapes.Clear();
            m_MeshColliderJobs.Dispose();
            m_MeshColliderVertices.Dispose();
            m_MeshColliderIndices.Dispose();
        }
예제 #7
0
    protected override unsafe void OnUpdate()
    {
        var preSpawnsAlreadyProcessed = EntityManager.CreateEntityQuery(ComponentType.ReadOnly <PreSpawnsInitialized>())
                                        .CalculateEntityCount();

        if (preSpawnsAlreadyProcessed > 0)
        {
            // Check if an uninitialized scene has appeared with no ghosts present inside, then just mark it as initialized and continue
            var prespawns = m_Prespawns.ToEntityArray(Allocator.TempJob);
            var newScenes = m_UninitializedScenes.ToEntityArray(Allocator.TempJob);
            for (int j = 0; j < newScenes.Length; ++j)
            {
                for (int i = 0; i < prespawns.Length; ++i)
                {
                    var scenes      = EntityManager.GetSharedComponentData <SceneSection>(prespawns[i]);
                    var sceneSystem = World.GetExistingSystem <SceneSystem>();
                    var sceneEntity = sceneSystem.GetSceneEntity(scenes.SceneGUID);
                    if (sceneEntity == newScenes[j])
                    {
                        UnityEngine.Debug.LogError("[" + World.Name +
                                                   "] Prespawned ghosts have already been initialized, this needs to happen for all subscenes at the same time.");
                        return;
                    }
                }
                EntityManager.AddComponent <PreSpawnsInitialized>(newScenes[j]);
            }
            newScenes.Dispose();
            prespawns.Dispose();
            return;
        }

        // Handle the chunk for an entity type, then handle each entity in the chunk (prespawned entities)
        var prespawnChunk   = m_Prespawns.CreateArchetypeChunkArray(Allocator.TempJob);
        var entityType      = GetEntityTypeHandle();
        var preSpawnedIds   = GetComponentDataFromEntity <PreSpawnedGhostId>();
        var subsceneMap     = new NativeMultiHashMap <ulong, Entity>(32, Allocator.Temp);
        var subscenePadding = new NativeHashMap <ulong, int>(32, Allocator.Temp);
        var ghostComponents = GetComponentDataFromEntity <GhostComponent>();

        // Put all known subscene hashes tracked by the prespawned ghosts into a map for sorting
        for (int i = 0; i < prespawnChunk.Length; ++i)
        {
            var chunk    = prespawnChunk[i];
            var entities = chunk.GetNativeArray(entityType);
            for (int j = 0; j < entities.Length; ++j)
            {
                var entity       = entities[j];
                var subsceneHash = EntityManager.GetSharedComponentData <SubSceneGhostComponentHash>(entity).Value;
                subsceneMap.Add(subsceneHash, entity);
            }
        }

        var subsceneArray = subsceneMap.GetUniqueKeyArray(Allocator.Temp);

        // Figure out scene id padding or how many IDs were used by the previous scenes in the sorted list, continue
        // where it left off so each ghost in a scene starts of at the ID+1 of last ghost in the previous scene
        var scenePadding = 0;

        for (int i = 0; i < subsceneArray.Item2; ++i)
        {
            subscenePadding.Add(subsceneArray.Item1[i], scenePadding);
            scenePadding += subsceneMap.CountValuesForKey(subsceneArray.Item1[i]);
        }

        var PostUpdateCommands          = new EntityCommandBuffer(Allocator.Temp);
        var serverSystems               = World.GetExistingSystem <ServerSimulationSystemGroup>();
        var ghostTypes                  = GetComponentDataFromEntity <GhostTypeComponent>();
        var ghostPrefabBufferFromEntity = GetBufferFromEntity <GhostPrefabBuffer>(true);
        var prefabEntity                = GetSingletonEntity <GhostPrefabCollectionComponent>();
        var ghostReceiveSystem          = World.GetExistingSystem <GhostReceiveSystem>();
        var ghostSendSystem             = World.GetExistingSystem <GhostSendSystem>();
        var ghostCollectionSystem       = World.GetExistingSystem <GhostCollectionSystem>();
        DynamicBuffer <GhostPrefabBuffer> prefabList = ghostPrefabBufferFromEntity[prefabEntity];
        int highestPrespawnId = -1;
        var spawnedGhosts     = new NativeList <SpawnedGhostMapping>(1024, Allocator.Temp);

        for (int i = 0; i < prespawnChunk.Length; ++i)
        {
            var chunk    = prespawnChunk[i];
            var entities = chunk.GetNativeArray(entityType);

            for (int j = 0; j < entities.Length; ++j)
            {
                var entity = entities[j];

                var ghostTypeComponent = ghostTypes[entity];
                int ghostType;
                for (ghostType = 0; ghostType < prefabList.Length; ++ghostType)
                {
                    if (ghostTypes[prefabList[ghostType].Value] == ghostTypeComponent)
                    {
                        break;
                    }
                }
                if (ghostType >= prefabList.Length)
                {
                    UnityEngine.Debug.LogError("Failed to look up ghost type for entity");
                    return;
                }

                // Check if this entity has already been handled
                if (ghostComponents[entity].ghostId != 0)
                {
                    UnityEngine.Debug.LogWarning(entity + " already has ghostId=" + ghostComponents[entity].ghostId + " prespawn=" + preSpawnedIds[entity].Value);
                    continue;
                }

                // Modfy the entity to its proper version
                if (EntityManager.HasComponent <GhostPrefabMetaDataComponent>(prefabList[ghostType].Value))
                {
                    ref var ghostMetaData = ref EntityManager.GetComponentData <GhostPrefabMetaDataComponent>(prefabList[ghostType].Value).Value.Value;
                    if (serverSystems != null)
                    {
                        for (int rm = 0; rm < ghostMetaData.RemoveOnServer.Length; ++rm)
                        {
                            var rmCompType = ComponentType.ReadWrite(TypeManager.GetTypeIndexFromStableTypeHash(ghostMetaData.RemoveOnServer[rm]));
                            PostUpdateCommands.RemoveComponent(entity, rmCompType);
                        }
                    }
                    else
                    {
                        for (int rm = 0; rm < ghostMetaData.RemoveOnClient.Length; ++rm)
                        {
                            var rmCompType = ComponentType.ReadWrite(TypeManager.GetTypeIndexFromStableTypeHash(ghostMetaData.RemoveOnClient[rm]));
                            PostUpdateCommands.RemoveComponent(entity, rmCompType);
                        }
                        // FIXME: should disable instead of removing once we have a way of doing that without structural changes
                        if (ghostMetaData.DefaultMode == GhostPrefabMetaData.GhostMode.Predicted)
                        {
                            for (int rm = 0; rm < ghostMetaData.DisableOnPredictedClient.Length; ++rm)
                            {
                                var rmCompType = ComponentType.ReadWrite(TypeManager.GetTypeIndexFromStableTypeHash(ghostMetaData.DisableOnPredictedClient[rm]));
                                PostUpdateCommands.RemoveComponent(entity, rmCompType);
                            }
                        }
                        else if (ghostMetaData.DefaultMode == GhostPrefabMetaData.GhostMode.Interpolated)
                        {
                            for (int rm = 0; rm < ghostMetaData.DisableOnInterpolatedClient.Length; ++rm)
                            {
                                var rmCompType = ComponentType.ReadWrite(TypeManager.GetTypeIndexFromStableTypeHash(ghostMetaData.DisableOnInterpolatedClient[rm]));
                                PostUpdateCommands.RemoveComponent(entity, rmCompType);
                            }
                        }
                    }
                }

                var subsceneHash = EntityManager.GetSharedComponentData <SubSceneGhostComponentHash>(entity).Value;
                var newId        = preSpawnedIds[entity].Value + subscenePadding[subsceneHash];
                if (newId > highestPrespawnId)
                {
                    highestPrespawnId = newId;
                }

                // If on a server we need to allocate the ghost ID for the pre-spawned entity so runtime spawns
                // will happen from the right start index
                if (serverSystems != null)
                {
                    spawnedGhosts.Add(new SpawnedGhostMapping {
                        ghost = new SpawnedGhost {
                            ghostId = newId, spawnTick = 0
                        }, entity = entity
                    });
                    var ghostSystemStateComponent = new GhostSystemStateComponent
                    {
                        ghostId = newId, despawnTick = 0, spawnTick = 0
                    };
                    PostUpdateCommands.AddComponent(entity, ghostSystemStateComponent);
                }
                else if (ghostReceiveSystem != null)
                {
                    var snapshotSize = ghostCollectionSystem.m_GhostTypeCollection[ghostType].SnapshotSize;
                    spawnedGhosts.Add(new SpawnedGhostMapping {
                        ghost = new SpawnedGhost {
                            ghostId = newId, spawnTick = 0
                        }, entity = entity
                    });
                    var newBuffer = PostUpdateCommands.SetBuffer <SnapshotDataBuffer>(entity);
                    newBuffer.ResizeUninitialized(snapshotSize * GhostSystemConstants.SnapshotHistorySize);
                    UnsafeUtility.MemClear(newBuffer.GetUnsafePtr(), snapshotSize * GhostSystemConstants.SnapshotHistorySize);
                    PostUpdateCommands.SetComponent(entity, new SnapshotData {
                        SnapshotSize = snapshotSize, LatestIndex = 0
                    });
                }

                // Pre-spawned uses spawnTick = 0, if there is a reference to a ghost and it has spawnTick 0 the ref is always resolved
                // This works because there despawns are high priority and we never create pre-spawned ghosts after connection
                var ghostComponent = new GhostComponent {
                    ghostId = newId, ghostType = ghostType, spawnTick = 0
                };
                PostUpdateCommands.SetComponent(entity, ghostComponent);

                // Mark scene as processed, as whole scene will have been loaded when this entity appeared
                var sceneSection = EntityManager.GetSharedComponentData <SceneSection>(entity);
                var sceneSystem  = World.GetExistingSystem <SceneSystem>();
                var sceneEntity  = sceneSystem.GetSceneEntity(sceneSection.SceneGUID);
                PostUpdateCommands.AddComponent <PreSpawnsInitialized>(sceneEntity);
            }
        }
예제 #8
0
    protected override unsafe void OnUpdate()
    {
        var preSpawnsAlreadyProcessed = EntityManager.CreateEntityQuery(ComponentType.ReadOnly <PreSpawnsInitialized>())
                                        .CalculateEntityCount();

        if (preSpawnsAlreadyProcessed > 0)
        {
            // Check if an uninitialized scene has appeared with no ghosts present inside, then just mark it as initialized and continue
            var prespawns = m_Prespawns.ToEntityArray(Allocator.TempJob);
            var newScenes = m_UninitializedScenes.ToEntityArray(Allocator.TempJob);
            for (int j = 0; j < newScenes.Length; ++j)
            {
                for (int i = 0; i < prespawns.Length; ++i)
                {
                    var scenes      = EntityManager.GetSharedComponentData <SceneSection>(prespawns[i]);
                    var sceneSystem = World.GetExistingSystem <SceneSystem>();
                    var sceneEntity = sceneSystem.GetSceneEntity(scenes.SceneGUID);
                    if (sceneEntity == newScenes[j])
                    {
                        UnityEngine.Debug.LogError("[" + World.Name +
                                                   "] Prespawned ghosts have already been initialized, this needs to happen for all subscenes at the same time.");
                        return;
                    }
                }
                EntityManager.AddComponent <PreSpawnsInitialized>(newScenes[j]);
            }
            newScenes.Dispose();
            prespawns.Dispose();
            return;
        }

        // Handle the chunk for an entity type, then handle each entity in the chunk (prespawned entities)
        var prespawnChunk   = m_Prespawns.CreateArchetypeChunkArray(Allocator.TempJob);
        var entityType      = GetEntityTypeHandle();
        var preSpawnedIds   = GetComponentDataFromEntity <PreSpawnedGhostId>();
        var subsceneMap     = new NativeMultiHashMap <ulong, Entity>(32, Allocator.Temp);
        var subscenePadding = new NativeHashMap <ulong, int>(32, Allocator.Temp);
        var ghostComponents = GetComponentDataFromEntity <GhostComponent>();

        // Put all known subscene hashes tracked by the prespawned ghosts into a map for sorting
        for (int i = 0; i < prespawnChunk.Length; ++i)
        {
            var chunk    = prespawnChunk[i];
            var entities = chunk.GetNativeArray(entityType);
            for (int j = 0; j < entities.Length; ++j)
            {
                var entity       = entities[j];
                var subsceneHash = EntityManager.GetSharedComponentData <SubSceneGhostComponentHash>(entity).Value;
                subsceneMap.Add(subsceneHash, entity);
            }
        }

        var subsceneArray = subsceneMap.GetUniqueKeyArray(Allocator.Temp);

        // Figure out scene id padding or how many IDs were used by the previous scenes in the sorted list, continue
        // where it left off so each ghost in a scene starts of at the ID+1 of last ghost in the previous scene
        var scenePadding = 0;

        for (int i = 0; i < subsceneArray.Item2; ++i)
        {
            subscenePadding.Add(subsceneArray.Item1[i], scenePadding);
            scenePadding += subsceneMap.CountValuesForKey(subsceneArray.Item1[i]);
        }

        var PostUpdateCommands  = new EntityCommandBuffer(Allocator.Temp);
        var serverSystems       = World.GetExistingSystem <ServerSimulationSystemGroup>();
        var ghostTypes          = GetComponentDataFromEntity <GhostTypeComponent>();
        var ghostReceiveSystem  = World.GetExistingSystem <GhostReceiveSystem>();
        var ghostSendSystem     = World.GetExistingSystem <GhostSendSystem>();
        var ghostTypeCollection = EntityManager.GetBuffer <GhostCollectionPrefabSerializer>(GetSingletonEntity <GhostCollection>());
        int highestPrespawnId   = -1;
        var spawnedGhosts       = new NativeList <SpawnedGhostMapping>(1024, Allocator.Temp);

        // Create a lookup from ghost type component to prefab entity, used to figure out how to strip components on the client
        var prefabFromType = new NativeHashMap <GhostTypeComponent, Entity>(1024, Allocator.Temp);

        Entities.WithNone <GhostPrefabRuntimeStrip>().WithAll <Prefab>().ForEach((Entity ent, in GhostTypeComponent ghostType) =>
        {
            prefabFromType.TryAdd(ghostType, ent);
        }).Run();

        for (int i = 0; i < prespawnChunk.Length; ++i)
        {
            var chunk    = prespawnChunk[i];
            var entities = chunk.GetNativeArray(entityType);

            for (int j = 0; j < entities.Length; ++j)
            {
                var entity = entities[j];

                var ghostTypeComponent = ghostTypes[entity];
                if (!prefabFromType.TryGetValue(ghostTypeComponent, out var ghostPrefabEntity))
                {
                    UnityEngine.Debug.LogError("Failed to look up ghost type for entity");
                    return;
                }

                // Check if this entity has already been handled
                if (ghostComponents[entity].ghostId != 0)
                {
                    UnityEngine.Debug.LogWarning(entity + " already has ghostId=" + ghostComponents[entity].ghostId + " prespawn=" + preSpawnedIds[entity].Value);
                    continue;
                }

                // Modfy the entity to its proper version
                if (EntityManager.HasComponent <GhostPrefabMetaDataComponent>(ghostPrefabEntity))
                {
                    ref var ghostMetaData     = ref EntityManager.GetComponentData <GhostPrefabMetaDataComponent>(ghostPrefabEntity).Value.Value;
                    var     linkedEntityGroup = EntityManager.GetBuffer <LinkedEntityGroup>(entity);
                    if (serverSystems != null)
                    {
                        for (int rm = 0; rm < ghostMetaData.RemoveOnServer.Length; ++rm)
                        {
                            var childIndexCompHashPair = ghostMetaData.RemoveOnServer[rm];
                            var rmCompType             = ComponentType.ReadWrite(TypeManager.GetTypeIndexFromStableTypeHash(childIndexCompHashPair.StableHash));
                            PostUpdateCommands.RemoveComponent(linkedEntityGroup[childIndexCompHashPair.EntityIndex].Value, rmCompType);
                        }
                    }
                    else
                    {
                        for (int rm = 0; rm < ghostMetaData.RemoveOnClient.Length; ++rm)
                        {
                            var childIndexCompHashPair = ghostMetaData.RemoveOnClient[rm];
                            var rmCompType             = ComponentType.ReadWrite(TypeManager.GetTypeIndexFromStableTypeHash(childIndexCompHashPair.StableHash));
                            PostUpdateCommands.RemoveComponent(linkedEntityGroup[childIndexCompHashPair.EntityIndex].Value, rmCompType);
                        }
                        // FIXME: should disable instead of removing once we have a way of doing that without structural changes
                        if (ghostMetaData.DefaultMode == GhostPrefabMetaData.GhostMode.Predicted)
                        {
                            for (int rm = 0; rm < ghostMetaData.DisableOnPredictedClient.Length; ++rm)
                            {
                                var childIndexCompHashPair = ghostMetaData.DisableOnPredictedClient[rm];
                                var rmCompType             = ComponentType.ReadWrite(TypeManager.GetTypeIndexFromStableTypeHash(childIndexCompHashPair.StableHash));
                                PostUpdateCommands.RemoveComponent(linkedEntityGroup[childIndexCompHashPair.EntityIndex].Value, rmCompType);
                            }
                        }
                        else if (ghostMetaData.DefaultMode == GhostPrefabMetaData.GhostMode.Interpolated)
                        {
                            for (int rm = 0; rm < ghostMetaData.DisableOnInterpolatedClient.Length; ++rm)
                            {
                                var childIndexCompHashPair = ghostMetaData.DisableOnInterpolatedClient[rm];
                                var rmCompType             = ComponentType.ReadWrite(TypeManager.GetTypeIndexFromStableTypeHash(childIndexCompHashPair.StableHash));
                                PostUpdateCommands.RemoveComponent(linkedEntityGroup[childIndexCompHashPair.EntityIndex].Value, rmCompType);
                            }
                        }
                    }
                }
예제 #9
0
        protected virtual int SetUpInventoryItems(InventoryGroupWrapper inventoryGroup, int itemCount, Entity owner)
        {
            var foodList        = new NativeList <ItemHashValue>(Allocator.Temp);
            var potionList      = new NativeList <ItemHashValue>(Allocator.Temp);
            var treasureList    = new NativeList <ItemHashValue>(Allocator.Temp);
            var weaponList      = new NativeList <ItemHashValue>(Allocator.Temp);
            var magicWeaponList = new NativeList <ItemHashValue>(Allocator.Temp);
            var helmetList      = new NativeList <ItemHashValue>(Allocator.Temp);
            var chestList       = new NativeList <ItemHashValue>(Allocator.Temp);
            var bootsList       = new NativeList <ItemHashValue>(Allocator.Temp);

            var itemCounter = 0;

            this.Entities.With(this._itemsGroup).ForEach((Entity itemEntity, ref ItemComponent itemComponent, ref PickedUpComponent pickedUpComponent) =>
            {
                if (pickedUpComponent.Owner != owner)
                {
                    return;
                }

                itemCounter++;
                var item = ItemsManagerComponent.Instance.ItemsStoreComponent.Items[itemComponent.StoreIndex];
                switch (item.ItemType)
                {
                case ItemType.Food:
                    foodList.Add(
                        new ItemHashValue
                    {
                        Entity        = itemEntity,
                        ItemComponent = itemComponent
                    });
                    break;

                case ItemType.Potion:
                    potionList.Add(
                        new ItemHashValue
                    {
                        Entity        = itemEntity,
                        ItemComponent = itemComponent
                    });
                    break;

                case ItemType.Treasure:
                    treasureList.Add(
                        new ItemHashValue
                    {
                        Entity        = itemEntity,
                        ItemComponent = itemComponent
                    });
                    break;

                case ItemType.Gear:
                    switch (item.GearType)
                    {
                    case GearType.Helmet:
                        helmetList.Add(
                            new ItemHashValue
                        {
                            Entity        = itemEntity,
                            ItemComponent = itemComponent
                        });
                        break;

                    case GearType.Chest:
                        chestList.Add(
                            new ItemHashValue
                        {
                            Entity        = itemEntity,
                            ItemComponent = itemComponent
                        });
                        break;

                    case GearType.Weapon:
                        weaponList.Add(
                            new ItemHashValue
                        {
                            Entity        = itemEntity,
                            ItemComponent = itemComponent
                        });
                        break;

                    case GearType.Boots:
                        bootsList.Add(
                            new ItemHashValue
                        {
                            Entity        = itemEntity,
                            ItemComponent = itemComponent
                        });
                        break;

                    case GearType.Magic:
                        magicWeaponList.Add(
                            new ItemHashValue
                        {
                            Entity        = itemEntity,
                            ItemComponent = itemComponent
                        });
                        break;
                    }
                    break;
                }
            });

            if (itemCounter != this.LastItemsCount || this.LastOwnerEntity != owner)
            {
                this.LastItemsCount  = itemCounter;
                this.LastOwnerEntity = owner;

                for (var i = inventoryGroup.Grid.transform.childCount - 1; i >= 0; i--)
                {
                    GameObject.Destroy(inventoryGroup.Grid.transform.GetChild(i).gameObject);
                }

                var itemsHashMap = new NativeMultiHashMap <int, ItemHashValue>(foodList.Length + potionList.Length + treasureList.Length, Allocator.Temp);
                for (var i = 0; i < foodList.Length; i++)
                {
                    itemsHashMap.Add(this.GetItemHash(foodList[i]), foodList[i]);
                }
                for (var i = 0; i < potionList.Length; i++)
                {
                    itemsHashMap.Add(this.GetItemHash(potionList[i]), potionList[i]);
                }
                for (var i = 0; i < treasureList.Length; i++)
                {
                    itemsHashMap.Add(this.GetItemHash(treasureList[i]), treasureList[i]);
                }

                if (itemsHashMap.Length > 0)
                {
                    var iterator = new NativeMultiHashMapIterator <int>();
                    var(keys, keysLength) = itemsHashMap.GetUniqueKeyArray(Allocator.Temp);
                    for (var keyI = 0; keyI < keysLength; keyI++)
                    {
                        if (!itemsHashMap.TryGetFirstValue(keys[keyI], out var hashValue, out iterator))
                        {
                            continue;
                        }

                        var button = this.AddInventoryButton(hashValue, inventoryGroup);

                        var itemsCount = 1;
                        while (itemsHashMap.TryGetNextValue(out hashValue, ref iterator))
                        {
                            itemsCount++;
                        }

                        if (itemsCount > 1)
                        {
                            button.Amount.text = itemsCount.ToString();
                        }
                        else
                        {
                            button.Amount.text = string.Empty;
                        }
                    }
                    keys.Dispose();
                }
                itemsHashMap.Dispose();

                for (var i = 0; i < weaponList.Length; i++)
                {
                    this.AddInventoryButton(weaponList[i], inventoryGroup);
                }
                for (var i = 0; i < magicWeaponList.Length; i++)
                {
                    this.AddInventoryButton(magicWeaponList[i], inventoryGroup);
                }
                for (var i = 0; i < helmetList.Length; i++)
                {
                    this.AddInventoryButton(helmetList[i], inventoryGroup);
                }
                for (var i = 0; i < chestList.Length; i++)
                {
                    this.AddInventoryButton(chestList[i], inventoryGroup);
                }
                for (var i = 0; i < bootsList.Length; i++)
                {
                    this.AddInventoryButton(bootsList[i], inventoryGroup);
                }
            }

            foodList.Dispose();
            potionList.Dispose();
            treasureList.Dispose();
            weaponList.Dispose();
            magicWeaponList.Dispose();
            helmetList.Dispose();
            chestList.Dispose();
            bootsList.Dispose();

            return(itemCounter);
        }