//TODO: There is too much code duplication here, refactor this to receive general artifacts from the editor unsafe void ReceiveSubSceneRefGUIDs(MessageEventArgs args) { fixed(byte *ptr = args.data) { var reader = new UnsafeAppendBuffer.Reader(ptr, args.data.Length); var subSceneAsset = reader.ReadNext <ResolvedSubSceneID>(); var sectionIndex = reader.ReadNext <int>(); reader.ReadNext(out NativeArray <RuntimeGlobalObjectId> objRefGUIDs, Allocator.Persistent); var refObjGUIDsPath = EntityScenesPaths.GetLiveLinkCachePath(subSceneAsset.TargetHash, EntityScenesPaths.PathType.EntitiesUnityObjectReferences, sectionIndex); // Not printing error because this can happen when running the same player multiple times on the same machine if (File.Exists(refObjGUIDsPath)) { LiveLinkMsg.LogInfo($"Received {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash} but it already exists on disk"); } else { LiveLinkMsg.LogInfo($"ReceieveSubSceneRefGUIDs => {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash},"); var tempCachePath = GetTempCachePath(); using (var writer = new StreamBinaryWriter(tempCachePath)) { writer.Write(objRefGUIDs.Length); writer.WriteArray(objRefGUIDs); } try { File.Move(tempCachePath, refObjGUIDsPath); } catch (Exception e) { File.Delete(tempCachePath); if (!File.Exists(refObjGUIDsPath)) { Debug.LogError($"Failed to move temporary file. Exception: {e.Message}"); LiveLinkMsg.LogInfo($"Failed to move temporary file. Exception: {e.Message}"); } } } if (!_WaitingForSubScenes.ContainsKey(subSceneAsset.SubSceneGUID)) { Debug.LogError($"Received {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash} without requesting it"); LiveLinkMsg.LogInfo($"Received {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash} without requesting it"); return; } var waitingSubScene = _WaitingForSubScenes[subSceneAsset.SubSceneGUID]; waitingSubScene.SubSections.Add(objRefGUIDs); _WaitingForSubScenes[subSceneAsset.SubSceneGUID] = waitingSubScene; } }
unsafe void ReceiveSubSceneHeader(MessageEventArgs args) { fixed(byte *ptr = args.data) { var reader = new UnsafeAppendBuffer.Reader(ptr, args.data.Length); var subSceneAsset = reader.ReadNext <ResolvedSubSceneID>(); var subSectionCount = reader.ReadNext <int>(); var headerPath = EntityScenesPaths.GetLiveLinkCachePath(subSceneAsset.TargetHash, EntityScenesPaths.PathType.EntitiesHeader, -1); // Not printing error because this can happen when running the same player multiple times on the same machine if (File.Exists(headerPath)) { LiveLinkMsg.LogInfo($"Received {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash} but it already exists on disk"); } else { var tempCachePath = GetTempCachePath(); LiveLinkMsg.LogInfo($"ReceiveSubSceneHeader => {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash}, '{tempCachePath}' => '{headerPath}'"); var stream = File.OpenWrite(tempCachePath); stream.Write(args.data, reader.Offset, args.data.Length - reader.Offset); stream.Close(); stream.Dispose(); try { File.Move(tempCachePath, headerPath); } catch (Exception e) { File.Delete(tempCachePath); if (!File.Exists(headerPath)) { Debug.LogError($"Failed to move temporary file. Exception: {e.Message}"); LiveLinkMsg.LogInfo($"Failed to move temporary file. Exception: {e.Message}"); } } } if (!_WaitingForSubScenes.ContainsKey(subSceneAsset.SubSceneGUID)) { Debug.LogError($"Received {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash} without requesting it"); LiveLinkMsg.LogInfo($"Received {subSceneAsset.SubSceneGUID} | {subSceneAsset.TargetHash} without requesting it"); return; } var waitingSubScene = _WaitingForSubScenes[subSceneAsset.SubSceneGUID]; waitingSubScene.TargetHash = subSceneAsset.TargetHash; waitingSubScene.SubSectionCount = subSectionCount; _WaitingForSubScenes[subSceneAsset.SubSceneGUID] = waitingSubScene; } }
//@TODO: Support some sort of transaction like API so we can reload all changed things in batch. unsafe void ReceiveAssetBundle(MessageEventArgs args) { LiveLinkMsg.LogReceived($"AssetBundle: '{args.data.Length}' bytes"); fixed(byte *ptr = args.data) { var reader = new UnsafeAppendBuffer.Reader(ptr, args.data.Length); var asset = reader.ReadNext <ResolvedAssetID>(); var assetBundleCachePath = GetCachePath(asset.TargetHash); var tempCachePath = GetTempCachePath(); // cache: look up asset by target hash to see if the version we want is already on the target device //if we already have the asset bundle revision we want, then just put that in the resolver as the active revision of the asset // cache: if not in cache, write actual file to Application.persistentDatapath var stream = File.OpenWrite(tempCachePath); stream.Write(args.data, reader.Offset, args.data.Length - reader.Offset); stream.Close(); stream.Dispose(); LiveLinkMsg.LogInfo($"ReceiveAssetBundle => {asset.GUID} | {asset.TargetHash}, '{tempCachePath}' => '{assetBundleCachePath}'"); if (File.Exists(assetBundleCachePath)) { Debug.LogError($"Received {asset.GUID} | {asset.TargetHash} but it already exists on disk"); LiveLinkMsg.LogInfo($"Received {asset.GUID} | {asset.TargetHash} but it already exists on disk"); File.Delete(tempCachePath); } else { try { File.Move(tempCachePath, assetBundleCachePath); } catch (Exception e) { File.Delete(tempCachePath); if (!File.Exists(assetBundleCachePath)) { Debug.LogError($"Failed to move temporary file. Exception: {e.Message}"); LiveLinkMsg.LogInfo($"Failed to move temporary file. Exception: {e.Message}"); } } } if (!_WaitingForAssets.ContainsKey(asset.GUID)) { Debug.LogError($"Received {asset.GUID} | {asset.TargetHash} without requesting it"); LiveLinkMsg.LogInfo($"Received {asset.GUID} | {asset.TargetHash} without requesting it"); } _WaitingForAssets[asset.GUID] = asset.TargetHash; } }
public ResourcePacket(byte[] buffer) { fixed(byte *ptr = buffer) { var bufferReader = new UnsafeAppendBuffer.Reader(ptr, buffer.Length); bufferReader.ReadNext(out GlobalObjectIds, Allocator.Persistent); var entityChangeSetSourcePtr = bufferReader.Ptr + bufferReader.Offset; var entityChangeSetSourceSize = bufferReader.Size - bufferReader.Offset; ChangeSet = new UnsafeAppendBuffer(entityChangeSetSourceSize, 16, Allocator.Persistent); ChangeSet.Add(entityChangeSetSourcePtr, entityChangeSetSourceSize); } }
unsafe void ReceiveSubScene(MessageEventArgs args) { fixed(byte *ptr = args.data) { var reader = new UnsafeAppendBuffer.Reader(ptr, args.data.Length); reader.ReadNext(out ResolvedSubSceneID subSceneId); reader.ReadNext(out NativeArray <RuntimeGlobalObjectId> runtimeGlobalObjectIds, Allocator.Persistent); LiveLinkMsg.LogInfo($"ReceiveSubScene => SubScene received {subSceneId} | Asset Dependencies {runtimeGlobalObjectIds.Length}"); if (!IsSubSceneAvailable(subSceneId)) { Debug.LogError("SubScene is missing artifacts!"); return; } AddWaitForSubScene(subSceneId, runtimeGlobalObjectIds); } }
void Deserialize(ref UnsafeAppendBuffer.Reader buffer, Allocator allocator) { buffer.ReadNext(out LoadedScenes, allocator); buffer.ReadNext(out RemovedScenes, allocator); }
public void Playback(ref ManagedDeferredCommands managedDeferredCommands) { var reader = new UnsafeAppendBuffer.Reader(ref managedDeferredCommands.CommandBuffer); while (!reader.EndOfBuffer) { var cmd = reader.ReadNext <int>(); switch ((ManagedDeferredCommands.Command)cmd) { case (ManagedDeferredCommands.Command.IncrementSharedComponentVersion): { var sharedIndex = reader.ReadNext <int>(); IncrementSharedComponentVersion(sharedIndex); } break; case (ManagedDeferredCommands.Command.CopyManagedObjects): { var srcArchetype = (Archetype *)reader.ReadNext <IntPtr>(); var srcManagedArrayIndex = reader.ReadNext <int>(); var srcChunkCapacity = reader.ReadNext <int>(); var srcStartIndex = reader.ReadNext <int>(); var dstArchetype = (Archetype *)reader.ReadNext <IntPtr>(); var dstManagedArrayIndex = reader.ReadNext <int>(); var dstChunkCapacity = reader.ReadNext <int>(); var dstStartIndex = reader.ReadNext <int>(); var count = reader.ReadNext <int>(); CopyManagedObjects(this, srcArchetype, srcManagedArrayIndex, srcChunkCapacity, srcStartIndex, this, dstArchetype, dstManagedArrayIndex, dstChunkCapacity, dstStartIndex, count); } break; case (ManagedDeferredCommands.Command.ReplicateManagedObjects): { var srcArchetype = (Archetype *)reader.ReadNext <IntPtr>(); var srcManagedArrayIndex = reader.ReadNext <int>(); var srcChunkCapacity = reader.ReadNext <int>(); var srcIndex = reader.ReadNext <int>(); var dstArchetype = (Archetype *)reader.ReadNext <IntPtr>(); var dstManagedArrayIndex = reader.ReadNext <int>(); var dstChunkCapacity = reader.ReadNext <int>(); var dstBaseStartIndex = reader.ReadNext <int>(); var count = reader.ReadNext <int>(); var srcEntity = reader.ReadNext <Entity>(); reader.ReadNext <Entity>(out var dstEntities, Allocator.Temp); ReplicateManagedObjects(this, srcArchetype, srcManagedArrayIndex, srcChunkCapacity, srcIndex, this, dstArchetype, dstManagedArrayIndex, dstChunkCapacity, dstBaseStartIndex, count, srcEntity, dstEntities); } break; case (ManagedDeferredCommands.Command.ClearManagedObjects): { var archetype = (Archetype *)reader.ReadNext <IntPtr>(); var managedArrayIndex = reader.ReadNext <int>(); var chunkCapacity = reader.ReadNext <int>(); var index = reader.ReadNext <int>(); var count = reader.ReadNext <int>(); ClearManagedObjects(archetype, managedArrayIndex, chunkCapacity, index, count); } break; case (ManagedDeferredCommands.Command.AddReference): { var index = reader.ReadNext <int>(); var numRefs = reader.ReadNext <int>(); AddReference(index, numRefs); } break; case (ManagedDeferredCommands.Command.RemoveReference): { var index = reader.ReadNext <int>(); var numRefs = reader.ReadNext <int>(); RemoveReference(index, numRefs); } break; case (ManagedDeferredCommands.Command.DeallocateManagedArrayStorage): { var index = reader.ReadNext <int>(); DeallocateManagedArrayStorage(index); } break; case (ManagedDeferredCommands.Command.AllocateManagedArrayStorage): { var index = reader.ReadNext <int>(); var length = reader.ReadNext <int>(); AllocateManagedArrayStorage(index, length); } break; case (ManagedDeferredCommands.Command.ReserveManagedArrayStorage): { var count = reader.ReadNext <int>(); ReserveManagedArrayStorage(count); } break; case (ManagedDeferredCommands.Command.MoveChunksManagedObjects): { var oldArchetype = (Archetype *)reader.ReadNext <IntPtr>(); var oldManagedArrayIndex = reader.ReadNext <int>(); var newArchetype = (Archetype *)reader.ReadNext <IntPtr>(); var newManagedArrayIndex = reader.ReadNext <int>(); var chunkCapacity = reader.ReadNext <int>(); var count = reader.ReadNext <int>(); CopyManagedObjects(this, oldArchetype, oldManagedArrayIndex, chunkCapacity, 0, this, newArchetype, newManagedArrayIndex, chunkCapacity, 0, count); } break; case (ManagedDeferredCommands.Command.PatchManagedEntities): { var archetype = (Archetype *)reader.ReadNext <IntPtr>(); var chunk = (Chunk *)reader.ReadNext <IntPtr>(); var entityCount = reader.ReadNext <int>(); var remapping = (EntityRemapUtility.EntityRemapInfo *)reader.ReadNext <IntPtr>(); var allocator = (Allocator)reader.ReadNext <int>(); PatchEntities(this, archetype, chunk, entityCount, remapping, allocator); } break; case (ManagedDeferredCommands.Command.PatchManagedEntitiesForPrefabs): { var archetype = (Archetype *)reader.ReadNext <IntPtr>(); var chunk = (Chunk *)reader.ReadNext <IntPtr>(); var indexInChunk = reader.ReadNext <int>(); var entityCount = reader.ReadNext <int>(); var remapping = (EntityRemapUtility.SparseEntityRemapInfo *)reader.ReadNext <IntPtr>(); var remappingCount = reader.ReadNext <int>(); var allocator = (Allocator)reader.ReadNext <int>(); PatchEntitiesForPrefab(this, archetype, chunk, indexInChunk, entityCount, remapping, remappingCount, allocator); } break; } } managedDeferredCommands.Reset(); }
public void Playback(ref ManagedDeferredCommands managedDeferredCommands) { var reader = new UnsafeAppendBuffer.Reader(ref managedDeferredCommands.CommandBuffer); while (!reader.EndOfBuffer) { var cmd = reader.ReadNext <int>(); switch ((ManagedDeferredCommands.Command)cmd) { case (ManagedDeferredCommands.Command.IncrementSharedComponentVersion): { var sharedIndex = reader.ReadNext <int>(); IncrementSharedComponentVersion(sharedIndex); } break; case (ManagedDeferredCommands.Command.AddReference): { var index = reader.ReadNext <int>(); var numRefs = reader.ReadNext <int>(); AddReference(index, numRefs); } break; case (ManagedDeferredCommands.Command.RemoveReference): { var index = reader.ReadNext <int>(); var numRefs = reader.ReadNext <int>(); RemoveReference(index, numRefs); } break; case (ManagedDeferredCommands.Command.PatchManagedEntities): { var archetype = (Archetype *)reader.ReadNext <IntPtr>(); var chunk = (Chunk *)reader.ReadNext <IntPtr>(); var entityCount = reader.ReadNext <int>(); var remapping = (EntityRemapUtility.EntityRemapInfo *)reader.ReadNext <IntPtr>(); PatchEntities(archetype, chunk, entityCount, remapping); } break; case (ManagedDeferredCommands.Command.PatchManagedEntitiesForPrefabs): { var remapSrc = (byte *)reader.ReadNext <IntPtr>(); var allocatedCount = reader.ReadNext <int>(); var remappingCount = reader.ReadNext <int>(); var numManagedComponents = reader.ReadNext <int>(); var allocator = (Allocator)reader.ReadNext <int>(); var remapSrcSize = UnsafeUtility.SizeOf <Entity>() * remappingCount; var remapDstSize = UnsafeUtility.SizeOf <Entity>() * remappingCount * allocatedCount; var remapDst = remapSrc + remapSrcSize; var managedComponents = remapDst + remapDstSize; PatchEntitiesForPrefab((int *)managedComponents, numManagedComponents, allocatedCount, remappingCount, (Entity *)remapSrc, (Entity *)remapDst); UnsafeUtility.Free(remapSrc, allocator); } break; case (ManagedDeferredCommands.Command.CloneManagedComponents): { var srcArray = (int *)reader.ReadNextArray <int>(out var componentCount); var instanceCount = reader.ReadNext <int>(); var dstArray = (int *)reader.ReadNextArray <int>(out _); CloneManagedComponents(srcArray, componentCount, dstArray, instanceCount); } break; case (ManagedDeferredCommands.Command.CloneHybridComponents): { var srcArray = (int *)reader.ReadNextArray <int>(out var componentCount); var entities = (Entity *)reader.ReadNextArray <Entity>(out var instanceCount); var dstArray = (int *)reader.ReadNextArray <int>(out _); if (InstantiateHybridComponent != null) { InstantiateHybridComponent(srcArray, componentCount, entities, dstArray, instanceCount, this); } else { // InstantiateHybridComponent was not injected just copy the reference to the object and dont clone it for (int src = 0; src < componentCount; ++src) { object sourceComponent = m_ManagedComponentData[srcArray[src]]; for (int i = 0; i < instanceCount; ++i) { m_ManagedComponentData[dstArray[i]] = sourceComponent; } dstArray += instanceCount; } } } break; case (ManagedDeferredCommands.Command.FreeManagedComponents): { var count = reader.ReadNext <int>(); for (int i = 0; i < count; ++i) { var managedComponentIndex = reader.ReadNext <int>(); m_ManagedComponentData[managedComponentIndex] = null; } } break; case (ManagedDeferredCommands.Command.SetManagedComponentCapacity): { var capacity = reader.ReadNext <int>(); SetManagedComponentCapacity(capacity); } break; } } managedDeferredCommands.Reset(); }