/// <summary> /// Establish new game session. /// If the player is a guest, they must first download the game settings first (not implemented) /// </summary> /// <returns>True if the establishment is successful or false on failure</returns> public void Establish() { _tokenSource = new CancellationTokenSource(); _cancelToken = _tokenSource.Token; // change multiplayer game state depending on role switch (_role) { case MultiplayerRole.Guest: var task = Firebase.Get(GetLink("state")); task.Wait(); // malformed state if (!int.TryParse(task.Result, out int _state)) { Close(); } GameState state = (GameState)_state; if (state == GameState.Connecting || state == GameState.Waiting) { CurrentData.ChangeGameState(GameState.Playing); } break; case MultiplayerRole.Host: CurrentData.ChangeGameState(GameState.Waiting); break; } // overall upload task _uploadTask = UploadTask.CreateInstance(_cancelToken); // overall download task _downloadTask = DownloadTask.CreateInstance(_cancelToken, (result) => { // must try here because exception could throw in following code of try block try { // the result will be merged Logger.Log(result); MergeData(result); } catch (Exception e) { Logger.Log("Exception raised: " + e.Message); Close(); } }); // main task to initiate both uploading and downloading tasks _mainTask = Task.Run(() => { PlayerData data = _role == MultiplayerRole.Host ? CurrentData.Host : CurrentData.Guest; while (!_cancelToken.IsCancellationRequested) { Logger.Log("Doing main task here..."); data.Time = TimePlayed; UploadData(data); DownloadData(); Thread.Sleep(1000); } }, _cancelToken); // set a running thread for closing connection from another thread Task.Run(() => { // preventing multiple threads "data racing" with closing this connection // only one thread can request closing the connection // the thread that is trying to close is actually a part // of one player's program that is passively waiting // for further instruction on closing the multiplayer game // -> the last one to close is the one to delete data, simple while (!_requestCloseConnection && !IsConnectionClosed) { } Close(true); }); }