public unsafe void Execute(Entity entity, int index, [ReadOnly] ref CommandTargetComponent commandTarget) { if (commandTarget.targetEntity == Entity.Null) { return; } var buffer = cmdBuffer[entity]; if (buffer.Length == 0) { return; } DataStreamReader reader = DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)buffer.GetUnsafePtr(), buffer.Length); var ctx = default(DataStreamReader.Context); var tick = reader.ReadUInt(ref ctx); var receivedCommand = default(TCommandData); receivedCommand.Deserialize(tick, reader, ref ctx); buffer.Clear(); // Store received commands in the network command buffer var command = commandData[commandTarget.targetEntity]; command.AddCommandData(receivedCommand); }
protected unsafe override void OnUpdate() { // TODO: LZ: // not use Allocator.Persistent var ents = m_RpcBufferQuery.ToEntityArray(Allocator.TempJob); for (var i = 0; i < ents.Length; ++i) { var ent = ents[i]; var rpcBuf = EntityManager.GetBuffer <IncomingRpcDataStreamBufferComponent>(ent); DataStreamReader reader = DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)rpcBuf.GetUnsafePtr(), rpcBuf.Length); var ctx = default(DataStreamReader.Context); while (reader.GetBytesRead(ref ctx) < reader.Length) { int type = reader.ReadInt(ref ctx); if (type < m_InternalRpcCollectionLength) { m_InternalRpcCollection.ExecuteRpc(type, reader, ref ctx, ent, PostUpdateCommands); } else { m_RpcCollection.ExecuteRpc(type - m_InternalRpcCollectionLength, reader, ref ctx, ent, PostUpdateCommands); } } rpcBuf.Clear(); } ents.Dispose(); }
public unsafe void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { var entities = chunk.GetNativeArray(entityType); var bufferAccess = chunk.GetBufferAccessor(bufferType); for (int i = 0; i < bufferAccess.Length; ++i) { var dynArray = bufferAccess[i]; DataStreamReader reader = DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)dynArray.GetUnsafePtr(), dynArray.Length); var ctx = default(DataStreamReader.Context); while (reader.GetBytesRead(ref ctx) < reader.Length) { int type = reader.ReadInt(ref ctx); if (type < internalRpcCollectionLength) { internalRpcCollection.ExecuteRpc(type, reader, ref ctx, entities[i], commandBuffer, chunkIndex); } else { rpcCollection.ExecuteRpc(type - internalRpcCollectionLength, reader, ref ctx, entities[i], commandBuffer, chunkIndex); } } dynArray.Clear(); } }
public unsafe void Execute(Entity entity, int index, [ReadOnly] ref PlayerStateComponentData playerState) { if (playerState.PlayerShip == Entity.Null) { return; } var buffer = cmdBuffer[entity]; if (buffer.Length == 0) { return; } DataStreamReader reader = DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)buffer.GetUnsafePtr(), buffer.Length); var ctx = default(DataStreamReader.Context); var inputTick = reader.ReadUInt(ref ctx); var left = reader.ReadByte(ref ctx); var right = reader.ReadByte(ref ctx); var thrust = reader.ReadByte(ref ctx); var shoot = reader.ReadByte(ref ctx); buffer.Clear(); //Debug.Log("Input delay: " + (int)(currentTick - inputTick)); // If ship, store commands in network command buffer var input = shipInput[playerState.PlayerShip]; input.mostRecentPos = (input.mostRecentPos + 1) % 32; input.tick[input.mostRecentPos] = inputTick; input.left[input.mostRecentPos] = left; input.right[input.mostRecentPos] = right; input.thrust[input.mostRecentPos] = thrust; input.shoot[input.mostRecentPos] = shoot; shipInput[playerState.PlayerShip] = input; }
public unsafe void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { var entities = chunk.GetNativeArray(entityType); var bufferAccess = chunk.GetBufferAccessor(bufferType); for (int i = 0; i < bufferAccess.Length; ++i) { var dynArray = bufferAccess[i]; DataStreamReader reader = DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)dynArray.GetUnsafePtr(), dynArray.Length); var ctx = default(DataStreamReader.Context); while (reader.GetBytesRead(ref ctx) < reader.Length) { int type = reader.ReadInt(ref ctx); switch (type) { case 0: { var tmp = new RpcSetNetworkId(); tmp.Deserialize(reader, ref ctx); tmp.Execute(entities[i], commandBuffer, chunkIndex); break; } case 1: { var tmp = new RpcLoadLevel(); tmp.Deserialize(reader, ref ctx); tmp.Execute(entities[i], commandBuffer, chunkIndex); break; } case 2: { var tmp = new RpcLevelLoaded(); tmp.Deserialize(reader, ref ctx); tmp.Execute(entities[i], commandBuffer, chunkIndex); break; } case 3: { var tmp = new RpcSpawn(); tmp.Deserialize(reader, ref ctx); tmp.Execute(entities[i], commandBuffer, chunkIndex); break; } } } dynArray.Clear(); } }
public unsafe void Execute(Entity entity, int index, [ReadOnly] ref CommandTargetComponent commandTarget, ref NetworkSnapshotAckComponent snapshotAck) { if (typeof(TCommandData) == typeof(NullCommandData) && commandTarget.targetEntity != Entity.Null) { return; } if (typeof(TCommandData) != typeof(NullCommandData) && !commandData.Exists(commandTarget.targetEntity)) { return; } var buffer = cmdBuffer[entity]; if (buffer.Length < 4) { return; } DataStreamReader reader = DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)buffer.GetUnsafePtr(), buffer.Length); var ctx = default(DataStreamReader.Context); var tick = reader.ReadUInt(ref ctx); int age = (int)(serverTick - tick); age *= 256; snapshotAck.ServerCommandAge = (snapshotAck.ServerCommandAge * 7 + age) / 8; if (commandTarget.targetEntity != Entity.Null && buffer.Length > 4) { var command = commandData[commandTarget.targetEntity]; var baselineReceivedCommand = default(TCommandData); baselineReceivedCommand.Deserialize(tick, reader, ref ctx); // Store received commands in the network command buffer command.AddCommandData(baselineReceivedCommand); for (uint i = 1; i < CommandSendSystem <TCommandData> .k_InputBufferSendSize; ++i) { var receivedCommand = default(TCommandData); receivedCommand.Deserialize(tick - i, reader, ref ctx, baselineReceivedCommand, compressionModel); // Store received commands in the network command buffer command.AddCommandData(receivedCommand); } } #if UNITY_EDITOR || DEVELOPMENT_BUILD netStats[0] = serverTick; netStats[1] += (uint)buffer.Length + 16u; // 16 is the ack fields which are already processed #endif buffer.Clear(); }
private unsafe void OnArrayProcess(NativeArray <Entity> entities, NativeArray <CommandTargetComponent> targetArray) { var serverTick = World.GetExistingSystem <ServerSimulationSystemGroup>().ServerTick; for (var ent = 0; ent < entities.Length; ent++) { var target = targetArray[ent]; if (target.targetEntity == default) { continue; } var buffer = EntityManager.GetBuffer <IncomingCommandDataStreamBufferComponent>(entities[ent]); if (buffer.Length <= 0) { continue; } var reader = DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)buffer.GetUnsafePtr(), buffer.Length); var ctx = default(DataStreamReader.Context); var tick = reader.ReadUInt(ref ctx); var age = (int)(serverTick - tick); age *= 256; var snapshotAck = EntityManager.GetComponentData <NetworkSnapshotAckComponent>(entities[ent]); snapshotAck.ServerCommandAge = (snapshotAck.ServerCommandAge * 7 + age) / 8; EntityManager.SetComponentData(entities[ent], snapshotAck); while (reader.GetBytesRead(ref ctx) < reader.Length) { var type = reader.ReadByte(ref ctx); if (!m_CommandCollectionSystem.SystemProcessors.TryGetValue(type, out var processor)) { throw new KeyNotFoundException($"No processor with type '{type}' found!"); } processor.BeginDeserialize(target.targetEntity, type); processor.ProcessReceive(serverTick, reader, ref ctx, m_NetworkCompressionModel); } buffer.Clear(); } }
public unsafe void Execute() { // FIXME: should handle any number of connections with individual ghost mappings for each #if ENABLE_UNITY_COLLECTIONS_CHECKS if (players.Length > 1) { throw new InvalidOperationException("Ghost receive system only supports a single connection"); } #endif while (delayedDespawnQueue.Count > 0 && !SequenceHelpers.IsNewer(delayedDespawnQueue.Peek().tick, targetTick)) { commandBuffer.RemoveComponent(delayedDespawnQueue.Dequeue().ghost, replicatedEntityType); } var snapshot = snapshotFromEntity[players[0]]; if (snapshot.Length == 0) { return; } var dataStream = DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)snapshot.GetUnsafePtr(), snapshot.Length); // Read the ghost stream // find entities to spawn or destroy var readCtx = new DataStreamReader.Context(); var serverTick = dataStream.ReadUInt(ref readCtx); var ack = snapshotAckFromEntity[players[0]]; if (ack.LastReceivedSnapshotByLocal != 0 && !SequenceHelpers.IsNewer(serverTick, ack.LastReceivedSnapshotByLocal)) { return; } if (ack.LastReceivedSnapshotByLocal != 0) { ack.ReceivedSnapshotByLocalMask <<= (int)(serverTick - ack.LastReceivedSnapshotByLocal); } ack.ReceivedSnapshotByLocalMask |= 1; ack.LastReceivedSnapshotByLocal = serverTick; snapshotAckFromEntity[players[0]] = ack; uint despawnLen = dataStream.ReadUInt(ref readCtx); uint updateLen = dataStream.ReadUInt(ref readCtx); #if ENABLE_UNITY_COLLECTIONS_CHECKS int startPos = dataStream.GetBitsRead(ref readCtx); #endif for (var i = 0; i < despawnLen; ++i) { int ghostId = (int)dataStream.ReadPackedUInt(ref readCtx, compressionModel); GhostEntity ent; if (!ghostEntityMap.TryGetValue(ghostId, out ent)) { continue; } ghostEntityMap.Remove(ghostId); // if predicted, despawn now, otherwise wait if (predictedFromEntity.Exists(ent.entity)) { commandBuffer.RemoveComponent(ent.entity, replicatedEntityType); } else { delayedDespawnQueue.Enqueue(new DelayedDespawnGhost { ghost = ent.entity, tick = serverTick }); } } #if ENABLE_UNITY_COLLECTIONS_CHECKS netStats[0] = despawnLen; netStats[1] = (uint)(dataStream.GetBitsRead(ref readCtx) - startPos); netStats[2] = 0; for (int i = 0; i < serializers.Length; ++i) { netStats[i * 3 + 3] = 0; netStats[i * 3 + 4] = 0; netStats[i * 3 + 5] = 0; } uint statCount = 0; uint uncompressedCount = 0; #endif uint targetArch = 0; uint targetArchLen = 0; uint baselineTick = 0; uint baselineTick2 = 0; uint baselineTick3 = 0; uint baselineLen = 0; int newGhosts = 0; for (var i = 0; i < updateLen; ++i) { if (targetArchLen == 0) { #if ENABLE_UNITY_COLLECTIONS_CHECKS int curPos = dataStream.GetBitsRead(ref readCtx); if (statCount > 0) { int statType = (int)targetArch; netStats[statType * 3 + 3] = netStats[statType * 3 + 3] + statCount; netStats[statType * 3 + 4] = netStats[statType * 3 + 4] + (uint)(curPos - startPos); netStats[statType * 3 + 5] = netStats[statType * 3 + 5] + uncompressedCount; } startPos = curPos; statCount = 0; uncompressedCount = 0; #endif targetArch = dataStream.ReadPackedUInt(ref readCtx, compressionModel); targetArchLen = dataStream.ReadPackedUInt(ref readCtx, compressionModel); } --targetArchLen; if (baselineLen == 0) { baselineTick = serverTick - dataStream.ReadPackedUInt(ref readCtx, compressionModel); baselineTick2 = serverTick - dataStream.ReadPackedUInt(ref readCtx, compressionModel); baselineTick3 = serverTick - dataStream.ReadPackedUInt(ref readCtx, compressionModel); baselineLen = dataStream.ReadPackedUInt(ref readCtx, compressionModel); } --baselineLen; int ghostId = (int)dataStream.ReadPackedUInt(ref readCtx, compressionModel); GhostEntity gent; if (ghostEntityMap.TryGetValue(ghostId, out gent)) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (gent.ghostType != targetArch) { throw new InvalidOperationException("Received a ghost with an invalid ghost type"); } //throw new InvalidOperationException("Received a ghost with an invalid ghost type " + targetArch + ", expected " + gent.ghostType); #endif serializers.Deserialize((int)targetArch, gent.entity, serverTick, baselineTick, baselineTick2, baselineTick3, dataStream, ref readCtx, compressionModel); } else { ++newGhosts; serializers.Spawn((int)targetArch, ghostId, serverTick, dataStream, ref readCtx, compressionModel); } #if ENABLE_UNITY_COLLECTIONS_CHECKS ++statCount; if (baselineTick == serverTick) { ++uncompressedCount; } #endif } #if ENABLE_UNITY_COLLECTIONS_CHECKS if (statCount > 0) { int curPos = dataStream.GetBitsRead(ref readCtx); int statType = (int)targetArch; netStats[statType * 3 + 3] = netStats[statType * 3 + 3] + statCount; netStats[statType * 3 + 4] = netStats[statType * 3 + 4] + (uint)(curPos - startPos); netStats[statType * 3 + 5] = netStats[statType * 3 + 5] + uncompressedCount; } #endif while (ghostEntityMap.Capacity < ghostEntityMap.Length + newGhosts) { ghostEntityMap.Capacity += 1024; } }
public unsafe void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { var entities = chunk.GetNativeArray(entityType); var rpcInBuffer = chunk.GetBufferAccessor(inBufferType); var rpcOutBuffer = chunk.GetBufferAccessor(outBufferType); var connections = chunk.GetNativeArray(connectionType); for (int i = 0; i < rpcInBuffer.Length; ++i) { if (driver.GetConnectionState(connections[i].Value) != NetworkConnection.State.Connected) { continue; } var dynArray = rpcInBuffer[i]; var reader = DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)dynArray.GetUnsafePtr(), dynArray.Length); var parameters = new RpcExecutor.Parameters { Reader = reader, ReaderContext = default(DataStreamReader.Context), CommandBuffer = commandBuffer, Connection = entities[i], JobIndex = chunkIndex }; while (reader.GetBytesRead(ref parameters.ReaderContext) < reader.Length) { var rpcIndex = reader.ReadUShort(ref parameters.ReaderContext); if (rpcIndex == ushort.MaxValue) { // Special value for NetworkProtocolVersion var netCodeVersion = reader.ReadInt(ref parameters.ReaderContext); var gameVersion = reader.ReadInt(ref parameters.ReaderContext); var rpcVersion = reader.ReadULong(ref parameters.ReaderContext); if (netCodeVersion != protocolVersion.NetCodeVersion || gameVersion != protocolVersion.GameVersion || rpcVersion != protocolVersion.RpcCollectionVersion) { commandBuffer.AddComponent(chunkIndex, entities[i], new NetworkStreamRequestDisconnect { Reason = NetworkStreamDisconnectReason.BadProtocolVersion }); #if ENABLE_UNITY_COLLECTIONS_CHECKS throw new InvalidOperationException("Network protocol mismatch"); #else return; #endif } } else if (rpcIndex >= execute.Length) { #if ENABLE_UNITY_COLLECTIONS_CHECKS throw new InvalidOperationException("Received an invalid RPC"); #else return; #endif } else { execute[rpcIndex].Execute.Ptr.Invoke(ref parameters); } } dynArray.Clear(); var sendBuffer = rpcOutBuffer[i]; if (sendBuffer.Length > 0) { DataStreamWriter tmp = new DataStreamWriter(sendBuffer.Length, Allocator.Temp); tmp.WriteBytes((byte *)sendBuffer.GetUnsafePtr(), sendBuffer.Length); driver.Send(reliablePipeline, connections[i].Value, tmp); sendBuffer.Clear(); } } }