private void ClientSyncLoop() { //clear the clients list _clients.Clear(); int decodeErrors = 0; //if the JSON is unreadable - new version likely using (var reader = new StreamReader(_tcpClient.GetStream(), Encoding.UTF8)) { try { var sideInfo = _clientStateSingleton.PlayerCoaltionLocationMetadata; //start the loop off by sending a SYNC Request SendToServer(new NetworkMessage { Client = new SRClient { Coalition = sideInfo.side, Name = sideInfo.name.Length > 0 ? sideInfo.name : _clientStateSingleton.LastSeenName, Position = sideInfo.Position, ClientGuid = _guid }, MsgType = NetworkMessage.MessageType.SYNC, }); string line; while ((line = reader.ReadLine()) != null) { try { var serverMessage = JsonConvert.DeserializeObject <NetworkMessage>(line); decodeErrors = 0; //reset counter if (serverMessage != null) { switch (serverMessage.MsgType) { case NetworkMessage.MessageType.PING: // Do nothing for now break; case NetworkMessage.MessageType.RADIO_UPDATE: case NetworkMessage.MessageType.UPDATE: _serverSettings.Decode(serverMessage.ServerSettings); if (_clients.ContainsKey(serverMessage.Client.ClientGuid)) { var srClient = _clients[serverMessage.Client.ClientGuid]; var updatedSrClient = serverMessage.Client; if (srClient != null) { srClient.LastUpdate = DateTime.Now.Ticks; srClient.Name = updatedSrClient.Name; srClient.Coalition = updatedSrClient.Coalition; srClient.Position = updatedSrClient.Position; srClient.LatLngPosition = updatedSrClient.LatLngPosition; if (updatedSrClient.RadioInfo != null) { srClient.RadioInfo = updatedSrClient.RadioInfo; srClient.RadioInfo.LastUpdate = DateTime.Now.Ticks; } else { //radio update but null RadioInfo means no change if (serverMessage.MsgType == NetworkMessage.MessageType.RADIO_UPDATE) { srClient.RadioInfo.LastUpdate = DateTime.Now.Ticks; } } // Logger.Info("Recevied Update Client: " + NetworkMessage.MessageType.UPDATE + " From: " + // srClient.Name + " Coalition: " + // srClient.Coalition + " Pos: " + srClient.Position); } } else { var connectedClient = serverMessage.Client; connectedClient.LastUpdate = DateTime.Now.Ticks; //init with LOS true so you can hear them incase of bad DCS install where //LOS isnt working connectedClient.LineOfSightLoss = 0.0f; //0.0 is NO LOSS therefore full Line of sight _clients[serverMessage.Client.ClientGuid] = connectedClient; // Logger.Info("Recevied New Client: " + NetworkMessage.MessageType.UPDATE + // " From: " + // serverMessage.Client.Name + " Coalition: " + // serverMessage.Client.Coalition); } if (_clientStateSingleton.InExternalAWACSMode && !_serverSettings.GetSettingAsBool(Common.Setting.ServerSettingsKeys.EXTERNAL_AWACS_MODE)) { DisconnectExternalAWACSMode(); } CallUpdateUIOnMain(); break; case NetworkMessage.MessageType.SYNC: // Logger.Info("Recevied: " + NetworkMessage.MessageType.SYNC); //check server version if (serverMessage.Version == null) { Logger.Error("Disconnecting Unversioned Server"); Disconnect(); break; } var serverVersion = Version.Parse(serverMessage.Version); var protocolVersion = Version.Parse(UpdaterChecker.MINIMUM_PROTOCOL_VERSION); ServerVersion = serverMessage.Version; if (serverVersion < protocolVersion) { Logger.Error($"Server version ({serverMessage.Version}) older than minimum procotol version ({UpdaterChecker.MINIMUM_PROTOCOL_VERSION}) - disconnecting"); ShowVersionMistmatchWarning(serverMessage.Version); Disconnect(); break; } if (serverMessage.Clients != null) { foreach (var client in serverMessage.Clients) { client.LastUpdate = DateTime.Now.Ticks; //init with LOS true so you can hear them incase of bad DCS install where //LOS isnt working client.LineOfSightLoss = 0.0f; //0.0 is NO LOSS therefore full Line of sight _clients[client.ClientGuid] = client; } } //add server settings _serverSettings.Decode(serverMessage.ServerSettings); if (_clientStateSingleton.InExternalAWACSMode && !_serverSettings.GetSettingAsBool(Common.Setting.ServerSettingsKeys.EXTERNAL_AWACS_MODE)) { DisconnectExternalAWACSMode(); } CallUpdateUIOnMain(); break; case NetworkMessage.MessageType.SERVER_SETTINGS: // Logger.Info("Recevied: " + NetworkMessage.MessageType.SERVER_SETTINGS); _serverSettings.Decode(serverMessage.ServerSettings); ServerVersion = serverMessage.Version; if (_clientStateSingleton.InExternalAWACSMode && !_serverSettings.GetSettingAsBool(Common.Setting.ServerSettingsKeys.EXTERNAL_AWACS_MODE)) { DisconnectExternalAWACSMode(); } CallUpdateUIOnMain(); break; case NetworkMessage.MessageType.CLIENT_DISCONNECT: // Logger.Info("Recevied: " + NetworkMessage.MessageType.CLIENT_DISCONNECT); SRClient outClient; _clients.TryRemove(serverMessage.Client.ClientGuid, out outClient); if (outClient != null) { MessageHub.Instance.Publish(outClient); } break; case NetworkMessage.MessageType.VERSION_MISMATCH: Logger.Error($"Version Mismatch Between Client ({UpdaterChecker.VERSION}) & Server ({serverMessage.Version}) - Disconnecting"); ShowVersionMistmatchWarning(serverMessage.Version); Disconnect(); break; case NetworkMessage.MessageType.EXTERNAL_AWACS_MODE_PASSWORD: if (serverMessage.Client.Coalition == 0) { Logger.Info("External AWACS mode authentication failed"); CallExternalAWACSModeOnMain(false, 0); } else if (_radioDCSSync != null && _radioDCSSync.IsListening) { Logger.Info("External AWACS mode authentication succeeded, coalition {0}", serverMessage.Client.Coalition == 1 ? "red" : "blue"); CallExternalAWACSModeOnMain(true, serverMessage.Client.Coalition); _radioDCSSync.StartExternalAWACSModeLoop(); } break; default: Logger.Error("Recevied unknown " + line); break; } } } catch (Exception ex) { decodeErrors++; if (!_stop) { Logger.Error(ex, "Client exception reading from socket "); } if (decodeErrors > MAX_DECODE_ERRORS) { ShowVersionMistmatchWarning("unknown"); Disconnect(); break; } } // do something with line } } catch (Exception ex) { if (!_stop) { Logger.Error(ex, "Client exception reading - Disconnecting "); } } } //disconnected - reset DCS Info ClientStateSingleton.Instance.DcsPlayerRadioInfo.LastUpdate = 0; //clear the clients list _clients.Clear(); }