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; }
//TODO できればScene単位でパケットをまとめて、type(1byte) sceneHash(4byte)の5byteのデータを削減したい private void CreateRpcPacket(ref DataStreamWriter writer, ref DataStreamWriter rpcPacket, byte componentIndex, byte methodId) { unsafe { byte *dataPtr = DataStreamUnsafeUtility.GetUnsafeReadOnlyPtr(rpcPacket); writer.Write((byte)BuiltInPacket.Type.BehaviourRpc); writer.Write(sceneHash); writer.Write(netId); writer.Write(componentIndex); writer.Write(methodId); writer.WriteBytes(dataPtr, rpcPacket.Length); } }
protected DataStreamWriter CreateSendPacket(DataStreamWriter data, QosType qos, ushort targetId, ushort senderId) { unsafe { byte * dataPtr = DataStreamUnsafeUtility.GetUnsafeReadOnlyPtr(data); ushort dataLength = (ushort)data.Length; var writer = new DataStreamWriter(data.Length + 4, Allocator.Temp); writer.Write(targetId); writer.Write(senderId); writer.WriteBytes(dataPtr, data.Length); return(writer); } }
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(); }
protected DataStreamWriter CreateSendPacket(DataStreamWriter data, QosType qos, NativeList <ushort> targetIdList, ushort senderId) { unsafe { byte * dataPtr = DataStreamUnsafeUtility.GetUnsafeReadOnlyPtr(data); ushort dataLength = (ushort)data.Length; var writer = new DataStreamWriter(data.Length + 6 + targetIdList.Length * 2, Allocator.Temp); writer.Write(ushort.MaxValue - 1); writer.Write(senderId); writer.Write((ushort)targetIdList.Length); for (int i = 0; i < targetIdList.Length; i++) { writer.Write(targetIdList[i]); } writer.WriteBytes(dataPtr, data.Length); return(writer); } }
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(); } } }
public void Execute() { DataStreamReader stream; NetworkEvent.Type cmd; //前フレームで解決できなかったbufferedからuncheckedに登録. if (!savedUncheckedReliableDataStream.IsCreated) { stream = new DataStreamReader(savedUncheckedReliableDataStream, 0, savedUncheckedReliableDataStream.Length); int offset = 0; while (offset < savedUncheckedReliableDataStream.Length) { var readerCtx = default(DataStreamReader.Context); ushort length = stream.ReadUShort(ref readerCtx); if (0 < length && length <= savedUncheckedReliableDataStream.Length - offset - 2) { uncheckedreliableStreams.Add( new DataStreamReader(savedUncheckedReliableDataStream, offset + 2, length)); offset += length + 2; } else { break; } } } while ((cmd = connection.PopEvent(driver, out stream)) != NetworkEvent.Type.Empty) { if (cmd == NetworkEvent.Type.Connect) { flags[(int)FlagDef.IsConnected] = 1; Debug.Log("Connect : " + connection.InternalId); } else if (cmd == NetworkEvent.Type.Disconnect) { flags[(int)FlagDef.IsDisconnected] = 1; Debug.Log("Disconnect : " + connection.InternalId); } else if (cmd == NetworkEvent.Type.Data) { if (!stream.IsCreated) { continue; } var readerCtx = default(DataStreamReader.Context); byte qosType = stream.ReadByte(ref readerCtx); ushort seqNum = stream.ReadUShort(ref readerCtx); ushort ackNum = stream.ReadUShort(ref readerCtx); //if (qosType != (byte)QosType.MeasureLatency) { // Debug.Log ("Recieve Data Len=" + stream.Length + ",QoS=" + qosType + ",Seq=" + seqNum + ",Ack=" + ackNum); //} //最初のregister packetはseqNumに bool isInitialUpdate = flags[(int)FlagDef.IsNotInitialUpdate] == 0; //ackNumの更新 if (seqNumbers[(int)SeqNumberDef.OtherAck] != ackNum) { seqNumbers[(int)SeqNumberDef.OtherAck] = ackNum; //Debug.Log ("update OtherAck = " + ackNum + " first=" + isInitialUpdate); } switch ((QosType)qosType) { case QosType.MeasureLatency: long currentUnixTime = System.DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); long otherUnixTime = stream.ReadLong(ref readerCtx); seqNumbers[(int)SeqNumberDef.Latency] = (ushort)(currentUnixTime - otherUnixTime); break; case QosType.Unreliable: dataStreams.Add(stream); break; case QosType.Reliable: int seqNumberDiff = (int)seqNum - seqNumbers[(int)SeqNumberDef.OtherSeq]; if (!isInitialUpdate && seqNumberDiff > 1) { //Debug.Log ("Reliable seqNumberDiff > 1 recieve"); //順番が入れ替わってるからバッファに貯める if (seqNumberDiff - 2 < uncheckedreliableStreams.Length) { if (uncheckedreliableStreams[seqNumberDiff - 2].IsCreated) { uncheckedreliableStreams[seqNumberDiff - 2] = stream; } } else { uncheckedreliableStreams.Add(stream); } } else if (isInitialUpdate || (seqNumberDiff == 1 || seqNumberDiff == -ushort.MaxValue)) { flags[(int)FlagDef.IsNotInitialUpdate] = 1; //次の順のパケットなら確定する seqNumbers[(int)SeqNumberDef.OtherSeq] = seqNum; //Debug.Log ("update OtherSeq = " + seqNumbers[(int)SeqNumberDef.OtherSeq] + " first=" + isInitialUpdate); //AddChunksInDataStream (stream, ref readerCtx); dataStreams.Add(stream); //順番待ちのパケットを確定する while (uncheckedreliableStreams.Length != 0) { if (!uncheckedreliableStreams[0].IsCreated) { IncrementSequenceNumber(SeqNumberDef.OtherSeq); //Debug.Log ("update OtherSeq = " + seqNumbers[(int)SeqNumberDef.OtherSeq]); //AddChunksInDataStream (uncheckedreliableStreams[0], ref readerCtx); dataStreams.Add(uncheckedreliableStreams[0]); uncheckedreliableStreams.RemoveAtSwapBack(0); } else { break; } } } else { //受信済みのSeqNumのパケットなら無視 //Debug.Log ("Reliable same recieve"); } break; } } } //uncheckedreliableStreamsに残ったパケットはnetworkdriverから実態が消される前にコピーしておく unsafe { //uncheckedreliableStreamsはsavedUncheckedReliableDataStreamに実態を持つ場合があるので //直接savedUncheckedReliableDataStream書き込むと実態が消えてしまうのでtempまず書く tempUncheckedReliableDataStream.Clear(); for (int i = 0; i < uncheckedreliableStreams.Length; i++) { int dataLength = uncheckedreliableStreams[i].Length; if (tempUncheckedReliableDataStream.Capacity - tempUncheckedReliableDataStream.Length < dataLength + 2) { tempUncheckedReliableDataStream.Capacity *= 2; } byte *dataPtr = DataStreamUnsafeUtility.GetUnsafeReadOnlyPtr(uncheckedreliableStreams[i]); tempUncheckedReliableDataStream.Write(dataLength); tempUncheckedReliableDataStream.WriteBytes(dataPtr, dataLength); } savedUncheckedReliableDataStream.Clear(); if (savedUncheckedReliableDataStream.Capacity < tempUncheckedReliableDataStream.Capacity) { savedUncheckedReliableDataStream.Capacity *= tempUncheckedReliableDataStream.Capacity; } savedUncheckedReliableDataStream.WriteBytes( tempUncheckedReliableDataStream.GetUnsafeReadOnlyPtr(), tempUncheckedReliableDataStream.Length); } //次に自分が送るパケットでどこまで受け取ったか伝える. seqNumbers[(int)SeqNumberDef.SelfAck] = seqNumbers[(int)SeqNumberDef.OtherSeq]; }