public static DriveItem ToDriveItem(this RemoteState remoteState, bool deleted = false) { return(new DriveItem() { Deleted = deleted ? new Deleted() : null, File = remoteState.Type == DriveItemType.File ? new Microsoft.Graph.File() { Hashes = new Hashes() { QuickXorHash = remoteState.QuickXorHash } } : null, FileSystemInfo = new Microsoft.Graph.FileSystemInfo() { LastModifiedDateTime = remoteState.LastModified }, Folder = remoteState.Type == DriveItemType.Folder ? new Folder() : null, Id = remoteState.Id, Name = remoteState.Name, ParentReference = new ItemReference() { Path = $"{CryptoDriveConstants.PathPrefix}{remoteState.Path}", }, RemoteItem = remoteState.Type == DriveItemType.RemoteItem ? new RemoteItem() : null, Size = remoteState.Size }); }
public virtual void Set(bool state) { var command = Command.LocalRequest(state); LocalState.SendCommand(command, this); RemoteState.SendCommand(command, this); }
public void Send(byte[] data) { if (RemoteState != null) { RemoteState.Send(data); } }
/// <summary> /// Initializes a new instance of <see cref="AutoSaveTextFile{TUpdate}"/>. /// </summary> /// <param name="remoteState"> /// Object responsible for converting updates to text. /// </param> /// <param name="autoSaveFiles"> /// The <see cref="FileStreamPair"/> containing <see cref="FileStream"/>s to write to. /// Any existing contents in the files will be overwritten. /// <see cref="AutoSaveTextFile{TUpdate}"/> assumes ownership of the <see cref="FileStream"/>s /// so it takes care of disposing it after use. /// To be used as an auto-save <see cref="FileStream"/>, /// it must support seeking, reading and writing, and not be able to time out. /// </param> /// <exception cref="ArgumentNullException"> /// <paramref name="remoteState"/> and/or <paramref name="autoSaveFiles"/> are null. /// </exception> /// <exception cref="ArgumentException"> /// One or both <see cref="FileStream"/>s in <paramref name="autoSaveFiles"/> /// do not have the right capabilities to be used as an auto-save file stream. /// See also: <seealso cref="CanAutoSaveTo"/>. /// </exception> public AutoSaveTextFile(RemoteState remoteState, FileStreamPair autoSaveFiles) { if (remoteState == null) { throw new ArgumentNullException(nameof(remoteState)); } AutoSaveFiles = autoSaveFiles ?? throw new ArgumentNullException(nameof(autoSaveFiles)); // Assert capabilities of the file streams. VerifyFileStream(autoSaveFiles.FileStream1, nameof(autoSaveFiles)); VerifyFileStream(autoSaveFiles.FileStream2, nameof(autoSaveFiles)); // Immediately attempt to load the saved contents from either FileStream. // Choose first auto-save file to load from. FileStream latestAutoSaveFile = autoSaveFiles.FileStream1.Length == 0 ? autoSaveFiles.FileStream2 : autoSaveFiles.FileStream1; string loadedText = null; try { loadedText = Load(latestAutoSaveFile); } catch (Exception firstLoadException) { // Trace and try the other auto-save file as a backup. firstLoadException.Trace(); } // If null is returned from the first Load(), the integrity check failed. if (loadedText == null) { latestAutoSaveFile = autoSaveFiles.Different(latestAutoSaveFile); try { loadedText = Load(latestAutoSaveFile); } catch (Exception secondLoadException) { secondLoadException.Trace(); } } // Initialize remote state with the loaded text. // If both reads failed, loadedText == null. remoteState.Initialize(loadedText); // Initialize encoder and buffers. // Always use UTF8 for auto-saved text files. Encoding encoding = Encoding.UTF8; encoder = encoding.GetEncoder(); buffer = new char[CharBufferSize]; encodedBuffer = new byte[encoding.GetMaxByteCount(CharBufferSize)]; // Set up long running task to keep auto-saving updates. updateQueue = new ConcurrentQueue <TUpdate>(); cts = new CancellationTokenSource(); autoSaveBackgroundTask = Task.Run(() => AutoSaveLoop(latestAutoSaveFile, remoteState, cts.Token)); }
private RemoteState GetRemoteState(uint id) { RemoteState value = null; if (remoteStates.TryGetValue(id, out value)) { return(value); } value = new RemoteState(); remoteStates[id] = value; return(value); }
public void OnReceiveEventAck(NetHost client, NetStream stream, int containerFrameId) { int b = stream.ReadFrameId(containerFrameId); lock (remoteStates) { if (!client.isDyingForScopes) { RemoteState remoteState = GetRemoteState(client.hostId); remoteState.acknowledgedEvent = Mathf.Max(remoteState.acknowledgedEvent, b); } } }
private bool DoCloseConnection() { if (RemoteState != null) { RemoteState.GotDataToSend -= RemoteState_GotDataToSend; RemoteState.Close(); RemoteState = null; return(true); } else { return(false); } }
public void Disconnect() { if (RemoteState != null && RemoteState.Close()) { RemoteState = null; try { //Signal that we got disconnected if (Disconnected != null) { Disconnected(this, new NetworkEventArgs(Hostname, Port)); } } catch { } } }
void OnDrawGizmosSelected() { Gizmos.color = Color.green; RemoteState lastS = bufferedRemoteStates[0]; for (int i = 1; i < timestampCount; ++i) { Gizmos.DrawLine(lastS.pos, bufferedRemoteStates[i].pos); lastS = bufferedRemoteStates[i]; } Gizmos.color = Color.red; for (int i = 0; i < timestampCount; ++i) { Gizmos.DrawSphere(bufferedRemoteStates[i].pos, 0.05f); } }
void Update() { RemoteState input = Remote.Access(channel).state; TestButton(ref input, RemoteButton.Up, "D Pad/Up"); TestButton(ref input, RemoteButton.Down, "D Pad/Down"); TestButton(ref input, RemoteButton.Left, "D Pad/Left"); TestButton(ref input, RemoteButton.Right, "D Pad/Right"); TestButton(ref input, RemoteButton.One, "Button/1"); TestButton(ref input, RemoteButton.Two, "Button/2"); TestButton(ref input, RemoteButton.A, "Button/A"); TestButton(ref input, RemoteButton.B, "Button/B"); TestButton(ref input, RemoteButton.Minus, "Function/Minus"); TestButton(ref input, RemoteButton.Plus, "Function/Plus"); TestAcceleration(input.acc.x, "Accelerometer/X"); TestAcceleration(input.acc.y, "Accelerometer/Y"); TestAcceleration(input.acc.z, "Accelerometer/Z"); }
private void RemoteStateUpdateReceived(RemoteState state) { pendingActions.Enqueue(() => { if (gameStatus != GameStatus.KillCam) { allPlayers[state.id].UpdateScore(state.score); uiManager.UpdateScore(state.id, state.score); uiManager.UpdateHealth(state.id, state.health); if (state.health <= 0) { allPlayers[state.id].SetKilled(); if (state.id == mainPlayer.name) { uiManager.ShowMainPlayerKilledText(); } } } if (state.id != playerName || gameStatus == GameStatus.KillCam) { if (state.shooting != (int)GestureType.None) { allPlayers[state.id].SwitchWeapon((GestureType)state.shooting); allPlayers[state.id].SetShooting(true); } else { allPlayers[state.id].SetShooting(false); } Vector3 rotation = new Vector3(state.rotation[0], state.rotation[1], state.rotation[2]); allPlayers[state.id].transform.eulerAngles = rotation; } }); }
public virtual void ReceiveCommand(Command command) { LocalState.ReceiveCommand(command, this); RemoteState.ReceiveCommand(command, this); }
public void Collect() { bool flag = !NetGame.isClient && !ReplayRecorder.isPlaying; if (!isMasterSet || isMaster != flag) { isMasterSet = true; isMaster = flag; for (int i = 0; i < list.Count; i++) { list[i].SetMaster(isMaster); } } if (!exitingLevel && (NetGame.isServer || ReplayRecorder.isRecording)) { bool flag2 = !AllowSuspendCollect || !SuspendCollect || SnapshotCollect || ReplayRecorder.isRecording || !NetGame.isServer; SnapshotCollect = false; NetStream netStream = null; NetStream netStream2 = null; try { if (flag2) { netStream = NetStream.AllocStream(); for (int j = 0; j < list.Count; j++) { list[j].CollectState(netStream); } } if (eventStream != null && eventStream.position > 0) { eventStream.WriteNetId(0u); netStream2 = eventStream; eventStream = null; } if (ReplayRecorder.isRecording) { ReplayRecorder.instance.SubmitFrame(this, netStream, netStream2); } if (NetGame.isServer) { lock (remoteStates) { lock (frames.framesLock) { int num = 0; if (frames.frameQueue.Count > 0) { FrameState frameState = frames.frameQueue[0]; num = frameState.frameId; } int num2 = NetGame.serverFrameId - 60; foreach (KeyValuePair <uint, RemoteState> remoteState in remoteStates) { RemoteState value = remoteState.Value; if (value.acknowledgedFrame > 0) { if (value.acknowledgedFrame < num) { value.acknowledgedFrame = -1; } else { num2 = Mathf.Min(num2, value.acknowledgedFrame); } } if (value.firstFullStateFrame > 0) { if (value.firstFullStateFrame < num) { value.firstFullStateFrame = num; } else { num2 = Mathf.Min(num2, value.firstFullStateFrame); } } } if (frames.frameQueue.Count > 0) { int a = num2; FrameState frameState2 = frames.frameQueue[frames.frameQueue.Count - 1]; num2 = Mathf.Min(a, frameState2.frameId); } frames.DropOldEvents(NetGame.serverFrameId - 10); if (netStream2 != null) { frames.PushEvents(NetGame.serverFrameId, netStream2); } netStream2 = null; frames.DropOldStates(num2); if (netStream != null) { frames.PushState(NetGame.serverFrameId, netStream.AddRef()); } frames.LimitHistory(); if (NetGame.currentLevelInstanceID != 0 || !NetGame.isServer || this is NetPlayer) { bool flag3 = false; try { int frameId = NetGame.serverFrameId; if (netStream == null) { int num3 = frames.frameQueue.Count - 1; if (num3 >= 0) { FrameState frameState3 = frames.frameQueue[num3]; frameId = frameState3.frameId; FrameState frameState4 = frames.frameQueue[num3]; netStream = frameState4.stream.AddRef(); flag3 = true; } } if (netStream != null) { NetGame.instance.NotifyClients(this, frameId, NetGame.serverFrameId, netStream); } } finally { if (flag3 && netStream != null) { netStream = netStream.Release(); } } } } } } } finally { if (netStream != null) { netStream = netStream.Release(); } if (netStream2 != null) { netStream2 = netStream2.Release(); } } } }
public void NotifyClients(int serverFrameId, int timeId, NetStream fullMaster, NetHost conn) { NetStream netStream = null; int num = -1; int num2 = -1; try { lock (remoteStates) { if (conn.isDyingForScopes) { Debug.LogFormat("Attempt to send delta to client (id {0}) that is disconnecting - caught and rejected", conn.hostId); return; } RemoteState remoteState = GetRemoteState(conn.hostId); num = remoteState.acknowledgedFrame; if (num > 0) { lock (frames.framesLock) { NetStream state = frames.GetState(num); if (state != null) { netStream = NetStream.AllocStream(state); } } } if (netStream != null) { remoteState.lastFullStateFrame = -1; remoteState.firstFullStateFrame = -1; } else { int num3 = (!(suppressThrottling <= 0f)) ? 1 : 30; if (remoteState.lastFullStateFrame != -1 && timeId - remoteState.lastFullStateFrame < num3) { return; } remoteState.lastFullStateFrame = timeId; if (remoteState.firstFullStateFrame == -1) { remoteState.firstFullStateFrame = serverFrameId; } } } num2 = conn.GetWriteFrameId(serverFrameId); bool flag = true; if (AllowSuspendCollect) { flag = (netStream == null || serverFrameId != num); } if (flag) { NetStream netStream2 = NetStream.AllocStream(fullMaster); try { netStream2.Seek(0); NetStream netStream3 = NetGame.BeginMessage(NetMsgId.Delta); try { netStream3.WriteNetId(netId); netStream3.WriteFrameId((netStream != null) ? num : 0, num2); netStream3.WriteFrameId(serverFrameId, num2); if (num > 0) { NetGame.instance.clientLatency.ReportLatency(serverFrameId - num - 1); } for (int i = 0; i < list.Count; i++) { list[i].CalculateDelta(netStream, netStream2, netStream3); } NetGame.instance.SendUnreliable(conn, netStream3, num2); ReportDeltaBits(netStream3.position); } finally { if (netStream3 != null) { netStream3 = netStream3.Release(); } } } finally { if (netStream2 != null) { netStream2 = netStream2.Release(); } } } } finally { if (netStream != null) { netStream = netStream.Release(); } } num = -1; lock (remoteStates) { if (conn.isDyingForScopes) { Debug.LogFormat("Attempt to send delta to client (id {0}) that is disconnecting - caught and rejected [2]", conn.hostId); return; } num = GetRemoteState(conn.hostId).acknowledgedEvent; } NetStream netStream4 = NetGame.BeginMessage(NetMsgId.Event); try { netStream4.WriteNetId(netId); bool flag2 = false; lock (frames.framesLock) { for (int j = 0; j < frames.eventQueue.Count; j++) { FrameState frameState = frames.eventQueue[j]; if (frameState.frameId > num) { flag2 = true; NetStream netStream5 = netStream4; FrameState frameState2 = frames.eventQueue[j]; netStream5.WriteFrameId(frameState2.frameId, num2); NetStream netStream6 = netStream4; FrameState frameState3 = frames.eventQueue[j]; netStream6.WriteStream(frameState3.stream); } } } if (flag2) { netStream4.WriteFrameId(0, num2); NetGame.instance.SendUnreliable(conn, netStream4, num2); ReportEvenBits(netStream4.position); } } finally { if (netStream4 != null) { netStream4 = netStream4.Release(); } } }
private void TestButton(ref RemoteState input, RemoteButton button, string name) { transform.Find(name).GetComponent <Renderer>().material.color = input.IsPressed(button) ? Color.red : Color.white; }
void UpdateRemote() { viewPitchLerp = Mathf.Lerp(viewPitchLerp, viewPitch, 5 * Time.deltaTime); character.view.localRotation = Quaternion.AngleAxis(viewPitchLerp, Vector3.left); // This is the target playback time of the rigid body double interpolationTime = Time.timeAsDouble - settings.InterpolationDelay; // Use interpolation if the target playback time is present in the buffer if (bufferedRemoteStates[0].timestamp > interpolationTime) { for (int i = 0; i < timestampCount; ++i) { if (bufferedRemoteStates[i].timestamp <= interpolationTime || i == timestampCount - 1) { RemoteState rhs = bufferedRemoteStates[Mathf.Max(i - 1, 0)]; RemoteState lhs = bufferedRemoteStates[i]; // Use the time between the two slots to determine if interpolation is necessary double length = rhs.timestamp - lhs.timestamp; float t = 0.0f; if (length > 0.0001) { t = (float)((interpolationTime - lhs.timestamp) / length); } var position = Vector3.Lerp(lhs.pos, rhs.pos, t); transform.localRotation = Quaternion.Slerp(lhs.rot, rhs.rot, t); var diff = position - transform.position; if (diff.sqrMagnitude < 1) // Physics might cause the client-side to become desynced { characterController.Move(position - transform.position); } else { Teleport(position, transform.rotation); } IsSneaking = lhs.sneak; //Debug.DrawLine(transform.position + Vector3.up * 2, transform.position + Vector3.up * 3, Color.green); return; } } } else if (timestampCount > 1) { // Use extrapolation RemoteState latest = bufferedRemoteStates[0]; RemoteState latest2 = bufferedRemoteStates[Mathf.Min(1, timestampCount - 1)]; float extrapolationLength = (float)(interpolationTime - latest.timestamp); if (extrapolationLength < settings.ExtrapolationLimit) { var speed = latest.sneak ? settings.SneakSpeed : settings.runSpeed; var posDiffLastStates = latest.pos - latest2.pos; if (posDiffLastStates.sqrMagnitude > 0.1f) // Movement? { var estimatedVelocity = posDiffLastStates.normalized * speed; var extrapolatedPos = latest.pos + estimatedVelocity * extrapolationLength; characterController.Move(extrapolatedPos - transform.position); Debug.DrawLine(transform.position + Vector3.up * 2, transform.position + Vector3.up * 3, Color.blue); } } } else { RemoteState latest = bufferedRemoteStates[0]; characterController.Move(latest.pos); transform.localRotation = latest.rot; } }
private async Task AutoSaveLoop(FileStream lastWrittenToFile, RemoteState remoteState, CancellationToken ct) { for (; ;) { // If cancellation is requested, stop waiting so the queue can be emptied as quickly as possible. if (!ct.IsCancellationRequested) { try { await Task.Delay(AutoSaveDelay, ct); } catch { // If the task was cancelled, empty the queue before leaving this method. } } // Empty the queue, create a local (thread-safe) list of updates to process. bool hasUpdate = updateQueue.TryDequeue(out TUpdate firstUpdate); if (!hasUpdate) { // Only return if the queue is empty and saved. if (ct.IsCancellationRequested) { break; } } else { List <TUpdate> updates = new List <TUpdate> { firstUpdate }; while (updateQueue.TryDequeue(out TUpdate update)) { updates.Add(update); } try { if (remoteState.ShouldSave(updates, out string textToSave)) { // Alternate between both auto-save files. FileStream targetFile = AutoSaveFiles.Different(lastWrittenToFile); // Only truly necessary in the first iteration if the targetFile was initially a corrupt non-empty file. // Theoretically, two thrown writeExceptions would have the same effect. // In other cases, lastWrittenToFile.SetLength(0) below will already have done this. targetFile.SetLength(0); // Write the contents to the file. await WriteToFileAsync(targetFile, textToSave); // Only truncate the other file when completely successful, to indicate that // the auto-save file which was just saved is in a completely correct format. lastWrittenToFile.SetLength(0); // Switch to writing to the other file in the next iteration. lastWrittenToFile = targetFile; } } catch (Exception writeException) { writeException.Trace(); } } } }