private Aggregate <TData> ApplyEvent(Aggregate <TData> aggregate, Event <TDiff> @event) => new Aggregate <TData>() { Data = _differ.Patch(aggregate.Data, @event.EventData), Id = aggregate.Id, Version = @event.Version };
public Client( TRemoteState initialRemoteState, IReadOnlyDictionary <int, TLocalState> localStatesByTick, IDiffer <TLocalState> localStateDiffer, IDiffer <TRemoteState> remoteStateDiffer, EndPoint localEndPoint, EndPoint remoteEndPoint, TimeSpan sendInterval ) { if (!remoteStatesByTick.TryAdd(0, initialRemoteState)) { throw new InvalidOperationException("Could not add initial tick."); } connection = new Connection( localEndPoint, remoteEndPoint, (buffer, index, size) => { using (var reader = new BinaryReader(new MemoryStream(buffer, index, size, writable: false))) { totalBytesReceived += size; AckedLocalTick = reader.ReadInt32(); int oldRemoteTick = reader.ReadInt32(); int newRemoteTick = reader.ReadInt32(); //Console.WriteLine($"Received: ackedLocalTick = {ackedLocalTick}, oldRemoteTick = {oldRemoteTick}, newRemoteTick = {newRemoteTick}, ackingRemoteTick = {ackingRemoteTick}"); // only patch remote state if newer if (AckingRemoteTick < newRemoteTick) { var remoteState = remoteStatesByTick[oldRemoteTick]; remoteStateDiffer.Patch(ref remoteState, reader); if (!remoteStatesByTick.TryAdd(newRemoteTick, remoteState)) { throw new InvalidOperationException($"Could not add new tick {newRemoteTick}."); } AckingRemoteTick = newRemoteTick; } } }); sendThread = new Thread(() => { var memoryStream = new MemoryStream(); FixedTimer(_ => { if (!Connected) { return; } using (var writer = new BinaryWriter(memoryStream, Encoding.UTF8, leaveOpen: true)) { writer.SetOffset(0); writer.Write(AckingRemoteTick); TLocalState ackedLocalState; TLocalState localState; bool ticked; lock (localTickMutex) { writer.Write(AckedLocalTick); writer.Write(localTick); //Console.WriteLine($"Sending: ackingRemoteTick = {ackingRemoteTick}, ackedLocalTick = {ackedLocalTick}, localTick = {localTick}"); ticked = AckedLocalTick < localTick; ackedLocalState = localStatesByTick[AckedLocalTick]; localState = localStatesByTick[localTick]; } if (ticked) { localStateDiffer.Diff(ackedLocalState, localState, writer); } if (memoryStream.Position > int.MaxValue) { throw new OverflowException(); } connection.SendMessage(memoryStream.GetBuffer(), 0, writer.GetOffset()); totalBytesSent += writer.GetOffset(); } }, sendInterval, cancellationTokenSource.Token); }); sendThread.Start(); }