protected bool ReadChunkHeader(DataStreamReader stream, ref DataStreamReader.Context ctx , out DataStreamReader chunk, out DataStreamReader.Context ctx2, out ushort targetPlayerId, out ushort senderPlayerId) { chunk = default; ctx2 = default; targetPlayerId = 0; senderPlayerId = 0; int pos = stream.GetBytesRead(ref ctx); if (pos >= stream.Length) { return(false); } ushort dataLength = stream.ReadUShort(ref ctx); if (dataLength == 0) { return(false); } chunk = stream.ReadChunk(ref ctx, dataLength); targetPlayerId = chunk.ReadUShort(ref ctx2); senderPlayerId = chunk.ReadUShort(ref ctx2); return(true); }
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(); } }
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 bool Send(Room room, int toConnectionId, int fromConnectionId, DataStreamReader data) { if (ServerBehaviour.Config.BandwidthLimit > 0) { // Bandwidth control logic int taxedId = room.Server.ConnectionId == fromConnectionId ? toConnectionId : fromConnectionId; if (ContainsConnectedID(room.RoomId, taxedId)) { Client clientToBeTaxed = default(Client); foreach (Client c in connectedClients.GetValuesForKey(room.RoomId)) { if (c.ConnectionId == taxedId) { clientToBeTaxed = c; } } int bandwidthLimit = clientToBeTaxed.IsInBandwidthGracePeriod ? ServerBehaviour.Config.GracePeriodBandwidthLimit : ServerBehaviour.Config.BandwidthLimit; if (clientToBeTaxed.OutgoingBytes / (DateTime.UtcNow - clientToBeTaxed.ConnectTime).TotalSeconds > bandwidthLimit) { // Client used too much bandwidth. Disconnect them Console.WriteLine("[INFO] Bandwidth exceeded, client disconnected for overdue. The client is " + (clientToBeTaxed.IsInBandwidthGracePeriod ? "" : "not ") + "on grace period"); HandleClientDisconnect(room, taxedId, true); return(false); } // This includes relay overhead!! // TODO: Strip overhead clientToBeTaxed.OutgoingBytes += (ulong)data.Length; } } // Send the data DataStreamWriter writer; writer = driver.BeginSend(pipeline, connections[toConnectionId]); writer.WriteByte((byte)MessageType.Data); writer.WriteInt(fromConnectionId); unsafe { // Copy data from reader to writer byte *buffer; int len = data.Length - data.GetBytesRead(); data.ReadBytes((byte *)&buffer, len); writer.WriteBytes((byte *)&buffer, len); } driver.EndSend(writer); return(true); }
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(); } }
protected override void RecieveFragmentData(int hash, DataStreamReader stream, ref DataStreamReader.Context ctx, LargeBytesTransporter transporter) { int fragmentSize = stream.Length - stream.GetBytesRead(ref ctx); unsafe { fixed(byte *data = &transporter.data[transporter.pos]) { stream.ReadBytes(ref ctx, data, fragmentSize); transporter.pos += fragmentSize; } } //Debug.Log ("RecieveFragmentData Hash=" + transporter.hash + ", Pos" + transporter.pos); }
public static unsafe void Add <T>(this DynamicBuffer <T> self, ref DataStreamReader reader) where T : struct, IBufferElementData { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (UnsafeUtility.SizeOf <T>() != 1) { throw new System.InvalidOperationException("Can only Add to DynamicBuffers of size 1 from DataStreamReaders"); } #endif var oldLen = self.Length; var length = reader.Length - reader.GetBytesRead(); self.ResizeUninitialized(oldLen + length); reader.ReadBytes((byte *)self.GetUnsafePtr() + oldLen, length); }
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { var entities = chunk.GetNativeArray(entityType); var commandTargets = chunk.GetNativeArray(commandTargetType); var snapshotAckComponents = chunk.GetNativeArray(snapshotAckType); var inBuffer = chunk.GetBufferAccessor(inBufferType); for (int i = 0; i < entities.Length; i++) { if (commandTargets[i].Target == Entity.Null) { continue; } DynamicBuffer <TCommandData> cmdBuf = commandDatas[commandTargets[i].Target]; NetworkSnapshotAckComponent snapshotAck = snapshotAckComponents[i]; DataStreamReader reader = inBuffer[i].AsDataStreamReader(); while (reader.GetBytesRead() < reader.Length) { uint tick = reader.ReadUInt(); var serilaizer = default(TCommandSerializer); TCommandData cmd = default; cmd.Tick = tick; serilaizer.Deserialize(ref reader, ref cmd); int age = (int)(serverTick - cmd.Tick); age *= 256; snapshotAck.ServerCommandAge = (snapshotAck.ServerCommandAge * 7 + age) / 8; cmdBuf.AddCommandData(cmd); // 读取冗余输入 for (uint j = 1; j <= GlobalConstants.InputBufferSendSize; ++j) { cmd.Tick = tick - j; serilaizer.Deserialize(ref reader, ref cmd); cmdBuf.AddCommandData(cmd); } } snapshotAckComponents[i] = snapshotAck; inBuffer[i].Clear(); } }
protected override LargeBytesTransporter RecieveStart(int hash, DataStreamReader stream, ref DataStreamReader.Context ctx) { string name = stream.ReadString(ref ctx); int dataSize = stream.ReadInt(ref ctx); var transporter = new LargeBytesTransporter(hash, new byte[dataSize]); transporter.name = name; int fragmentSize = stream.Length - stream.GetBytesRead(ref ctx); unsafe { fixed(byte *data = &transporter.data[transporter.pos]) { stream.ReadBytes(ref ctx, data, fragmentSize); transporter.pos += fragmentSize; } } return(transporter); }
protected override void RecieveFragmentData(int hash, DataStreamReader stream, ref DataStreamReader.Context ctx, FileTransporter transporter) { int fragmentSize = stream.Length - stream.GetBytesRead(ref ctx); while (transporter.bufferPos + fragmentSize > transporter.buffer.Length) { transporter.Resize(transporter.buffer.Length * 2); //Debug.Log ("Resize Buffer " + transporter.buffer.Length); } unsafe { fixed(byte *data = &transporter.buffer[transporter.bufferPos]) { stream.ReadBytes(ref ctx, data, fragmentSize); transporter.bufferPos += fragmentSize; } } if (!transporter.isAwait) { var task = WriteBufferToFile(transporter); } }
protected override void OnUpdate() { if (m_PlayerQuery.IsEmptyIgnoreFilter) { m_DeserializeData.Entities.Clear(); m_DeserializeData.GhostIds.Clear(); m_DeserializeData.KnownArchetypes.Clear(); m_DeserializeData.GhostToEntityMap.Clear(); using (var replicatedEntities = m_ReplicatedQuery.ToEntityArray(Allocator.TempJob)) { foreach (var ent in replicatedEntities) { EntityManager.DestroyEntity(ent); } } return; } var player = m_PlayerQuery.GetSingletonEntity(); var incomingData = EntityManager.GetBuffer <IncomingSnapshotDataStreamBufferComponent>(player).Reinterpret <byte>(); if (incomingData.Length == 0) { return; } m_Dependency.Complete(); m_Dependency = default; var snapshot = incomingData.ToNativeArray(Allocator.TempJob); var reader = new DataStreamReader(snapshot); var ctx = default(DataStreamReader.Context); var snapshotCount = 0; while (reader.GetBytesRead(ref ctx) < reader.Length) { var safetyData = reader.ReadByte(ref ctx); var tick = reader.ReadUInt(ref ctx); var needDelay = false; Profiler.BeginSample("Apply Delayed"); if (tick != m_PreviousTick + 1 && m_PreviousTick != uint.MaxValue) { var isReliable = false; using (var snapshotEntities = m_Delayed.ToEntityArray(Allocator.TempJob)) using (var snapshotInfoArray = m_Delayed.ToComponentDataArray <DelayedSnapshotInfo>(Allocator.TempJob)) { var min = uint.MaxValue; var max = 0u; // get min-max first foreach (var info in snapshotInfoArray) { if (info.tick < min) { min = info.tick; } if (info.tick > max) { max = info.tick; } } // we can only continue if the incoming snapshot is right after the previous one if (max + 1 == tick) { isReliable = true; var targets = new NativeList <Entity>(snapshotEntities.Length, Allocator.Temp); var p = min; for (var index = 0; index < snapshotInfoArray.Length;) { var info = snapshotInfoArray[index]; if (p != info.tick) { index++; continue; } targets.Add(snapshotEntities[index]); p++; // reset index index = 0; } if (targets.Length != snapshotEntities.Length) { Debug.LogWarning("Did not get enough snapshots..."); isReliable = false; } if (isReliable) { for (var index = 0; index < targets.Length; index++) { using (var data = EntityManager.GetBuffer <DelayedSnapshotBuffer>(targets[index]) .Reinterpret <byte>() .ToNativeArray(Allocator.TempJob)) { var info = EntityManager.GetComponentData <DelayedSnapshotInfo>(targets[index]); ApplySnapshot(info.tick, data); } } EntityManager.DestroyEntity(m_Delayed); } } } if (!isReliable) { Debug.LogError($"Reliability issue, s={safetyData} p={m_PreviousTick} n={tick}"); needDelay = true; } } Profiler.EndSample(); Profiler.BeginSample("Apply current snapshot"); { var compressedSize = reader.ReadInt(ref ctx); var uncompressedSize = reader.ReadInt(ref ctx); var compressedMemory = new NativeArray <byte>(compressedSize, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); reader.ReadBytes(ref ctx, (byte *)compressedMemory.GetUnsafePtr(), compressedSize); var uncompressedMemory = new NativeArray <byte>(uncompressedSize, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); LastCompressedSnapshotSize = compressedSize; LastUncompressedSnapshotSize = uncompressedSize; Profiler.BeginSample("Decompress"); LZ4Codec.Decode((byte *)compressedMemory.GetUnsafePtr(), compressedSize, (byte *)uncompressedMemory.GetUnsafePtr(), uncompressedSize); Profiler.EndSample(); if (!needDelay) { ApplySnapshot(tick, uncompressedMemory); } else { var delayed = EntityManager.CreateEntity(typeof(DelayedSnapshotInfo), typeof(DelayedSnapshotBuffer)); EntityManager.GetBuffer <DelayedSnapshotBuffer>(delayed) .Reinterpret <byte>() .AddRange(uncompressedMemory); EntityManager.SetComponentData(delayed, new DelayedSnapshotInfo { tick = tick }); Debug.Log("Add delayed snapshot to the table..."); } uncompressedMemory.Dispose(); compressedMemory.Dispose(); snapshotCount++; } Profiler.EndSample(); } EntityManager.GetBuffer <IncomingSnapshotDataStreamBufferComponent>(player).Clear(); snapshot.Dispose(); }
private void ReadDataEvent(NetworkConnection connection, DataStreamReader streamReader) { try { int senderActorNumber = connection.InternalId; int command = streamReader.ReadInt(); switch (command) { case Commands.AcknowledgeActorNumber: { if (_acceptAllPlayers) { AcceptPlayer(senderActorNumber); } break; } case Commands.PlayerData: { string playerData = streamReader.ReadManagedString(); PlayerDataReceived?.Invoke(senderActorNumber, playerData); break; } case Commands.Ping: _lastPingTimes[connection] = Time; float sendLocalTime = streamReader.ReadFloat(); DataStreamWriter writer = _serverDriver.BeginSend(_unreliablePipeline, connection); writer.WriteInt(Commands.Ping); writer.WriteFloat(sendLocalTime); writer.WriteFloat(Time); writer.WriteFloat(UnityEngine.Time.deltaTime); _serverDriver.EndSend(writer); break; case Commands.RequestSpawnMessage: { var connections = new NativeList <NetworkConnection>(1, Allocator.Temp) { connection }; SendSpawnMessage(NetObjectManager.Instance.NetObjects, connections); connections.Dispose(); break; } case Commands.UpdateNetObjects: { int objectsInMessage = streamReader.ReadInt(); for (var obj = 0; obj < objectsInMessage; obj++) { int netObjID = streamReader.ReadInt(); int size = streamReader.ReadInt(); NetObject netObject = NetObjectManager.Instance.Exists(netObjID) ? NetObjectManager.Instance.Get(netObjID) : null; // ignore illegal updates and those from local host client if (netObject == null || netObject.OwnerActorNumber != senderActorNumber || // cheater? Client.IsHost && Client.Instance.ActorNumber == senderActorNumber) { streamReader.DiscardBytes(size); } else { int bytesRead = streamReader.GetBytesRead(); try { netObject.Deserialize(ref streamReader, b => b.ClientAuthoritative); } catch (Exception e) { Debug.LogException(e); int remainingBytes = size + bytesRead - streamReader.GetBytesRead(); streamReader.DiscardBytes(remainingBytes); } } } break; } case Commands.GameAction: { int gameActionID = streamReader.ReadInt(); int actorNumber = streamReader.ReadInt(); float triggerTime = streamReader.ReadFloat(); try { GameAction gameAction = GameActionManager.Instance.Get(gameActionID); GameAction.IParameters parameters = gameAction.DeserializeParameters(ref streamReader); gameAction.ReceiveOnServer(parameters, actorNumber, senderActorNumber, triggerTime); break; } catch (Exception e) { Debug.LogException(e); break; } } case Commands.NetAssetRPC: { float sentServerTime = streamReader.ReadFloat(); int netAssetID = streamReader.ReadInt(); NetAsset netAsset = NetAssetManager.Instance.Get(netAssetID); NetAsset.RPC rpc = netAsset.DeserializeRPC(ref streamReader); var messageInfo = new MessageInfo { SentServerTime = sentServerTime, SenderActorNumber = senderActorNumber }; rpc.Invoke(messageInfo); break; } case Commands.NetObjectRPC: { float sentServerTime = streamReader.ReadFloat(); int netObjectID = streamReader.ReadInt(); if (!NetObjectManager.Instance.Exists(netObjectID)) { Debug.LogWarning("Ignoring received RPC, because NetObject was not found."); break; } NetObject netObject = NetObjectManager.Instance.Get(netObjectID); ushort netBehaviourID = streamReader.ReadUShort(); NetBehaviour netBehaviour = netObject.Get(netBehaviourID); NetObjectManager.RPC rpc = NetObjectManager.Instance.DeserializeRPC(ref streamReader, netBehaviour); var messageInfo = new MessageInfo { SentServerTime = sentServerTime, SenderActorNumber = senderActorNumber }; rpc.Invoke(messageInfo); break; } default: Debug.LogException(new NetException($"Unknown command {command}")); break; } } catch (Exception e) { Debug.LogException(new NetException("Failed to handle data event", e)); } }