public void SetSharedComponentDataDeferred(EntityGuid entityGuid, int typeIndex, int afterSharedComponentIndex, int beforeSharedComponentIndex = -1) { m_DeferredSharedComponentChanges.Add(new DeferredPackedSharedComponentDataChange { EntityGuid = entityGuid, TypeIndex = typeIndex, AfterSharedComponentIndex = afterSharedComponentIndex, BeforeSharedComponentIndex = beforeSharedComponentIndex }); }
private PackedComponent PackComponent(EntityGuid entityGuid, int typeIndex, ulong stableTypeHash) { var flags = ComponentTypeFlags.None; if ((typeIndex & TypeManager.ChunkComponentTypeFlag) != 0) { flags |= ComponentTypeFlags.ChunkComponent; } var packedEntityIndex = PackedEntityCollection.GetOrAdd(entityGuid); var packedTypeIndex = PackedStableTypeHashCollection.GetOrAdd(new ComponentTypeHash { StableTypeHash = stableTypeHash, Flags = flags }); return(new PackedComponent { PackedEntityIndex = packedEntityIndex, PackedTypeIndex = packedTypeIndex }); }
public DuplicateEntityGuid(EntityGuid entityGuid, int duplicateCount) { EntityGuid = entityGuid; DuplicateCount = duplicateCount; }
private void SetComponentData( Chunk *afterChunk, Archetype *afterArchetype, ComponentTypeInArchetype afterTypeInArchetype, int afterIndexInTypeArray, int afterEntityIndexInChunk, Chunk *beforeChunk, Archetype *beforeArchetype, int beforeIndexInTypeArray, int beforeEntityIndexInChunk, EntityGuid entityGuid, int typeIndex, TypeInfo typeInfo) { if (afterTypeInArchetype.IsSharedComponent) { var beforeOffset = beforeIndexInTypeArray - beforeChunk->Archetype->FirstSharedComponent; var beforeSharedComponentIndex = beforeChunk->GetSharedComponentValue(beforeOffset); var afterOffset = afterIndexInTypeArray - afterChunk->Archetype->FirstSharedComponent; var afterSharedComponentIndex = afterChunk->GetSharedComponentValue(afterOffset); // No managed objects in burst land. Do what we can and defer the actual unpacking until later. ComponentDataStream.SetSharedComponentDataDeferred(entityGuid, afterTypeInArchetype.TypeIndex, afterSharedComponentIndex, beforeSharedComponentIndex); return; } // IMPORTANT This means `IsZeroSizedInChunk` which is always true for shared components. // Always check shared components first. if (afterTypeInArchetype.IsZeroSized) { return; } if (afterTypeInArchetype.IsBuffer) { var beforeBuffer = (BufferHeader *)(ChunkUtility.GetBuffer(beforeChunk) + beforeArchetype->Offsets[beforeIndexInTypeArray] + beforeEntityIndexInChunk * beforeArchetype->SizeOfs[beforeIndexInTypeArray]); var beforeElementPtr = BufferHeader.GetElementPointer(beforeBuffer); var beforeLength = beforeBuffer->Length; var afterBuffer = (BufferHeader *)(ChunkUtility.GetBuffer(afterChunk) + afterArchetype->Offsets[afterIndexInTypeArray] + afterEntityIndexInChunk * afterArchetype->SizeOfs[afterIndexInTypeArray]); var afterElementPtr = BufferHeader.GetElementPointer(afterBuffer); var afterLength = afterBuffer->Length; if (afterTypeInArchetype.TypeIndex == TypeInfoStream.LinkedEntityGroupTypeIndex) { var beforeLinkedEntityGroups = (LinkedEntityGroup *)beforeElementPtr; var afterLinkedEntityGroups = (LinkedEntityGroup *)afterElementPtr; // Using is not supported by burst. var beforeLinkedEntityGroupEntityGuids = new NativeArray <EntityGuid>(beforeLength, Allocator.Temp); var afterLinkedEntityGroupEntityGuids = new NativeArray <EntityGuid>(afterLength, Allocator.Temp); { for (var i = 0; i < beforeLength; i++) { if (!BeforeEntityToEntityGuid.TryGetValue(beforeLinkedEntityGroups[i].Value, out var beforeEntityGuid)) { throw new Exception("LinkedEntityGroup child is missing an EntityGuid component."); } beforeLinkedEntityGroupEntityGuids[i] = beforeEntityGuid; } for (var i = 0; i < afterLength; i++) { if (!AfterEntityToEntityGuid.TryGetValue(afterLinkedEntityGroups[i].Value, out var afterEntityGuid)) { throw new Exception("LinkedEntityGroup child is missing an EntityGuid component."); } afterLinkedEntityGroupEntityGuids[i] = afterEntityGuid; } beforeLinkedEntityGroupEntityGuids.Sort(); afterLinkedEntityGroupEntityGuids.Sort(); var beforeIndex = 0; var afterIndex = 0; while (beforeIndex < beforeLength && afterIndex < afterLength) { var beforeEntityGuid = beforeLinkedEntityGroupEntityGuids[beforeIndex]; var afterEntityGuid = afterLinkedEntityGroupEntityGuids[afterIndex]; var comparison = beforeEntityGuid.CompareTo(afterEntityGuid); if (comparison == 0) { // If the entity is in both "before" and "after", then there is no change. beforeIndex++; afterIndex++; } else if (comparison > 0) { // If the entity is in "before" but not "after", it's been removed. LinkedEntityGroupRemovals.Add(new LinkedEntityGroupChange { RootEntityGuid = entityGuid, ChildEntityGuid = beforeEntityGuid }); beforeIndex++; } else if (comparison < 0) { // If the entity is in "after" but not "before", it's been added. LinkedEntityGroupAdditions.Add(new LinkedEntityGroupChange { RootEntityGuid = entityGuid, ChildEntityGuid = afterEntityGuid }); afterIndex++; } } while (beforeIndex < beforeLength) { // If the entity is in "before" but not "after", it's been removed. LinkedEntityGroupRemovals.Add(new LinkedEntityGroupChange { RootEntityGuid = entityGuid, ChildEntityGuid = beforeLinkedEntityGroupEntityGuids[beforeIndex++] }); } while (afterIndex < afterLength) { // If the entity is in "after" but not "before", it's been added. LinkedEntityGroupAdditions.Add(new LinkedEntityGroupChange { RootEntityGuid = entityGuid, ChildEntityGuid = afterLinkedEntityGroupEntityGuids[afterIndex++] }); } } } else { if (afterLength != beforeLength || UnsafeUtility.MemCmp(beforeElementPtr, afterElementPtr, afterLength * typeInfo.ElementSize) != 0) { var packedComponent = PackComponent(entityGuid, typeIndex, typeInfo.StableTypeHash); ComponentDataStream.SetComponentData(packedComponent, afterElementPtr, typeInfo.ElementSize * afterLength); ExtractEntityReferencePatches(typeInfo, packedComponent, afterElementPtr, afterLength); } } } else { if (beforeArchetype->SizeOfs[beforeIndexInTypeArray] != afterArchetype->SizeOfs[afterIndexInTypeArray]) { throw new Exception("Archetype->SizeOfs do not match"); } var beforeAddress = ChunkUtility.GetBuffer(beforeChunk) + beforeArchetype->Offsets[beforeIndexInTypeArray] + beforeArchetype->SizeOfs[beforeIndexInTypeArray] * beforeEntityIndexInChunk; var afterAddress = ChunkUtility.GetBuffer(afterChunk) + afterArchetype->Offsets[afterIndexInTypeArray] + afterArchetype->SizeOfs[afterIndexInTypeArray] * afterEntityIndexInChunk; if (UnsafeUtility.MemCmp(beforeAddress, afterAddress, beforeArchetype->SizeOfs[beforeIndexInTypeArray]) != 0) { var packedComponent = PackComponent(entityGuid, typeIndex, typeInfo.StableTypeHash); ComponentDataStream.SetComponentData(packedComponent, afterAddress, beforeArchetype->SizeOfs[beforeIndexInTypeArray]); ExtractEntityReferencePatches(typeInfo, packedComponent, afterAddress, 1); } } }
private void AddComponentData( Chunk *afterChunk, Archetype *afterArchetype, ComponentTypeInArchetype afterTypeInArchetype, int afterIndexInTypeArray, int afterEntityIndexInChunk, EntityGuid entityGuid, int typeIndex, TypeInfo typeInfo ) { var packedComponent = PackComponent(entityGuid, typeIndex, typeInfo.StableTypeHash); AddComponents.Add(packedComponent); if (afterTypeInArchetype.IsSharedComponent) { var offset = afterIndexInTypeArray - afterChunk->Archetype->FirstSharedComponent; var sharedComponentIndex = afterChunk->GetSharedComponentValue(offset); // No managed objects in burst land. Do what we can a defer the actual unpacking until later. ComponentDataStream.SetSharedComponentDataDeferred(entityGuid, afterTypeInArchetype.TypeIndex, sharedComponentIndex); return; } // IMPORTANT This means `IsZeroSizedInChunk` which is always true for shared components. // Always check shared components first. if (afterTypeInArchetype.IsZeroSized) { // Zero sized components have no data to copy. return; } if (afterTypeInArchetype.IsBuffer) { var sizeOf = afterArchetype->SizeOfs[afterIndexInTypeArray]; var buffer = (BufferHeader *)(ChunkUtility.GetBuffer(afterChunk) + afterArchetype->Offsets[afterIndexInTypeArray] + afterEntityIndexInChunk * sizeOf); var length = buffer->Length; if (length == 0) { return; } var elementPtr = BufferHeader.GetElementPointer(buffer); if (afterTypeInArchetype.TypeIndex == TypeInfoStream.LinkedEntityGroupTypeIndex) { // Magic in AddComponent already put a self-reference at the top of the buffer, so there's no need for us to add it. // The rest of the elements should be interpreted as LinkedEntityGroupAdditions. for (var elementIndex = 1; elementIndex < length; elementIndex++) { var childEntity = ((Entity *)elementPtr)[elementIndex]; if (!AfterEntityToEntityGuid.TryGetValue(childEntity, out var childEntityGuid)) { // If the child entity doesn't have a guid, there's no way for us to communicate its identity to the destination world. throw new Exception("LinkedEntityGroup child is missing an EntityGuid component."); } LinkedEntityGroupAdditions.Add(new LinkedEntityGroupChange { RootEntityGuid = entityGuid, ChildEntityGuid = childEntityGuid }); } } else { ComponentDataStream.SetComponentData(packedComponent, elementPtr, typeInfo.ElementSize * length); ExtractEntityReferencePatches(typeInfo, packedComponent, elementPtr, length); } } else { var sizeOf = afterArchetype->SizeOfs[afterIndexInTypeArray]; var ptr = ChunkUtility.GetBuffer(afterChunk) + afterArchetype->Offsets[afterIndexInTypeArray] + afterEntityIndexInChunk * sizeOf; ComponentDataStream.SetComponentData(packedComponent, ptr, sizeOf); ExtractEntityReferencePatches(typeInfo, packedComponent, ptr, 1); } }