public void OnPlayerDisconnected(NetworkPlayer player) { var distancePlayer = GetDistancePlayer(player); distancePlayer.unityPlayer = player; if (distancePlayer.ReceivedInfo) { ValidPlayers.Remove(distancePlayer); for (int i = distancePlayer.Index; i < ValidPlayers.Count; i++) { ValidPlayers[i].Index = i; } } DistancePlayers.Remove(player.guid); distancePlayer.Car = null; DistanceServerMain.GetEvent <Events.ServerToClient.RemovePlayerFromClientList>().Fire( RPCMode.Others, new Distance::Events.ServerToClient.RemovePlayerFromClientList.Data(player, distancePlayer.Index, Distance::DisconnectionType.Quit) ); if (StartingMode) { AttemptToStartMode(); } distancePlayer.LeftAt = DistanceServerMain.UnixTime; distancePlayer.OnDisconnectedEvent.Fire(); OnPlayerDisconnectedEvent.Fire(distancePlayer); }
public void BroadcastDNF() { DistanceServerMain.GetEvent <Events.ServerToClient.GameModeFinished>().Fire( Player.UnityPlayer, new Distance::Events.GameMode.Finished.Data() ); }
public void TagPlayer(DistancePlayer player) { if (TaggedPlayer == player) { Log.Debug("Player same"); return; } if (player == null) { Log.Debug("Player null"); TaggedPlayer = null; return; } var lastTagData = TaggedPlayer?.GetExternalData <ReverseTagData>(); double lastSecondsTagged = lastTagData == null ? 0.0 : lastTagData.SecondsTagged; TimeOfLastTag = Plugin.Server.ModeTime; var networkTagData = new Distance::Events.ReverseTag.TaggedPlayer.Data(player.Index, lastSecondsTagged, TimeOfLastTag); DistanceServerMain.GetEvent <Events.ServerToClient.TaggedPlayer>().Fire(UnityEngine.RPCMode.Others, networkTagData); TaggedPlayer = player; LockTagBubbleFor(5); }
public void OnNeedToSyncLateClientToGameMode(DistancePlayer player) { DistanceServerMain.GetEvent <Events.ServerToClient.SyncMode>().Fire( player.UnityPlayer, new Distance::Events.GameMode.SyncMode.Data(Plugin.ServerStage == BasicAutoServer.Stage.AllFinished) ); }
public void OnPlayerConnected(NetworkPlayer player) { var distancePlayer = new DistancePlayer(this, player.guid); DistancePlayers[player.guid] = distancePlayer; foreach (var existingPlayer in ValidPlayers) { DistanceServerMain.GetEvent <Events.ServerToClient.AddClient>().Fire( player, existingPlayer.GetAddClientData(false) ); } foreach (var line in ChatLog) { distancePlayer.ChatLog.Add(line); } distancePlayer.ResendChat(); SendLevelInfo(player); DistanceServerMain.GetEvent <Events.ServerToClient.Request>().Fire( player, new Distance::Events.ServerToClient.Request.Data(Distance::ServerRequest.SubmitClientInfo) ); distancePlayer.JoinedAt = DistanceServerMain.UnixTime; OnPlayerConnectedEvent.Fire(distancePlayer); }
public void RequestSubmitGameModeInfo(NetworkPlayer player) { DistanceServerMain.GetEvent <Events.ServerToClient.Request>().Fire( player, new Distance::Events.ServerToClient.Request.Data(Distance::ServerRequest.SubmitGameModeInfo) ); }
public void SayChat(DistanceChat chat, bool addMessage = true) { AddChat(chat); DistanceServerMain.GetEvent <Events.ClientToAllClients.ChatMessage>().Fire( RPCMode.Others, new Distance::Events.ClientToAllClients.ChatMessage.Data(chat.Message) ); }
public void SayLocalChat(DistanceChat chat) { AddChat(chat); DistanceServerMain.GetEvent <Events.ClientToAllClients.ChatMessage>().Fire( UnityPlayer, new Distance::Events.ClientToAllClients.ChatMessage.Data(chat.Message) ); }
public void ResendChat() { string chatString = GetChatLogString(); Log.Debug($"Resending chat to {Name}:\n{chatString}"); DistanceServerMain.GetEvent <Events.ServerToClient.SetServerChat>().Fire( UnityPlayer, new Distance::Events.ServerToClient.SetServerChat.Data(chatString) ); }
public void SendPlayerToLobby(NetworkPlayer player) { var distancePlayer = GetDistancePlayer(player); distancePlayer.State = DistancePlayer.PlayerState.LoadingLobbyScene; distancePlayer.LevelId = CurrentLevelId; DistanceServerMain.GetEvent <Events.ServerToClient.Request>().Fire( player, new Distance::Events.ServerToClient.Request.Data(Distance::ServerRequest.LoadLobbyScene) ); }
public void SendLevelInfo(NetworkPlayer player) { DistanceServerMain.GetEvent <Events.ServerToClient.SetLevelName>().Fire( player, CurrentLevel.GetLevelNameData(HideLevelName, IsCustomPlaylist) ); DistanceServerMain.GetEvent <Events.ServerToClient.SetGameMode>().Fire( player, CurrentLevel.GetGameModeData() ); }
public void SendLobbyServerInfo(NetworkPlayer player) { DistanceServerMain.GetEvent <Events.ServerToClient.SetServerName>().Fire( player, new Distance::Events.ServerToClient.SetServerName.Data(ServerName) ); DistanceServerMain.GetEvent <Events.ServerToClient.SetMaxPlayers>().Fire( player, new Distance::Events.ServerToClient.SetMaxPlayers.Data(MaxPlayers) ); }
public void OnNeedToSyncLateClientToGameMode(DistancePlayer player) { DistanceServerMain.GetEvent <Events.ServerToClient.SyncMode>().Fire( player.UnityPlayer, new Distance::Events.GameMode.SyncMode.Data(Finished) ); if (TaggedPlayer != null) { DistanceServerMain.GetEvent <Events.ServerToClient.TaggedPlayer>().Fire( player.UnityPlayer, new Distance::Events.ReverseTag.TaggedPlayer.Data(TaggedPlayer.Index, 0.0, TimeOfLastTag) ); } }
public override void Start() { Connections.Add( DistanceServerMain.GetEvent <Events.Instanced.CarRespawn>().Connect(OnCarRespawn), DistanceServerMain.GetEvent <Events.ClientToServer.HitTagBubble>().Connect(OnHitTagBubble), Plugin.Server.OnNeedToSyncLateClientToGameMode.Connect(OnNeedToSyncLateClientToGameMode), Plugin.Server.OnCheckIfModeCanStartEvent.Connect(OnCheckIfModeCanStart), Plugin.OnCheckIfLevelCanAdvanceEvent.Connect(OnCheckIfModeCanAdvance), Plugin.Server.OnUpdateEvent.Connect(Update), Plugin.Server.OnPlayerConnectedEvent.Connect(OnPlayerConnected) ); foreach (var player in Plugin.Server.DistancePlayers.Values) { player.AddExternalData(new ReverseTagData()); } }
public void RequestLevelCompatibilityInfo(NetworkPlayer player) { DistanceServerMain.GetEvent <Events.ServerToClient.UpdatePlayerLevelCompatibilityStatus>().Fire( player, new Distance::Events.ServerToClient.UpdatePlayerLevelCompatibilityStatus.Data(player, Distance::LevelCompatabilityStatus.Unverified) ); DistanceServerMain.GetEvent <Events.ServerToClient.RequestLevelCompatabilityInfo>().Fire( player, new Distance::Events.ServerToClient.RequestLevelCompatabilityInfo.Data() { gameMode_ = CurrentLevel.GameMode, levelCompatInfoID_ = CurrentLevelId, levelName_ = CurrentLevel.Name, relativeLevelPath_ = CurrentLevel.RelativeLevelPath } ); }
public void SendPlayerToLevel(NetworkPlayer player) { SendLevelInfo(player); var distancePlayer = GetDistancePlayer(player); if (!UpdateLevelCompatabilityStatus(distancePlayer)) { distancePlayer.State = DistancePlayer.PlayerState.WaitingForCompatibilityStatus; return; } distancePlayer.State = DistancePlayer.PlayerState.LoadingGameModeScene; distancePlayer.Level = CurrentLevel; distancePlayer.LevelId = CurrentLevelId; DistanceServerMain.GetEvent <Events.ServerToClient.Request>().Fire( player, new Distance::Events.ServerToClient.Request.Data(Distance::ServerRequest.LoadGameModeScene) ); }
public System.Collections.IEnumerator StartModeAfterDelay(float delayTime) { StartingMode = false; StartingModeDelay = false; foreach (var player in ValidPlayers) { if (!player.HasLoadedLevel(true)) { player.Stuck = true; } } foreach (var player in ValidPlayers) { if (!player.Stuck && player.State == DistancePlayer.PlayerState.SubmittedGameModeInfo) { player.State = DistancePlayer.PlayerState.StartedMode; } } ModeStartTime = Network.time + 7.0 + delayTime; // Shift start sooner/later ModeTimeOffset = -ModeStartTime; ModeTime = 0.0; HasModeStarted = true; yield return(new WaitForSeconds(delayTime)); foreach (var player in ValidPlayers) { if (player.State == DistancePlayer.PlayerState.StartedMode) { DistanceServerMain.GetEvent <Events.ServerToClient.StartMode>().Fire( player.UnityPlayer, new Distance::Events.ServerToClient.StartMode.Data(ModeStartTime, false) ); } } OnModeStartedEvent.Fire(); }
public void UpdateCountdown(double value) { if (HasUnityPlayer && State == PlayerState.LoadedGameModeScene || State == PlayerState.SubmittedGameModeInfo || State == PlayerState.StartedMode) { if (value == -1.0) { if (Countdown != -1.0) { DistanceServerMain.GetEvent <Events.ServerToClient.FinalCountdownCancel>().Fire( UnityPlayer, new Distance::Events.RaceMode.FinalCountdownCancel.Data() ); } } else { DistanceServerMain.GetEvent <Events.ServerToClient.FinalCountdownActivate>().Fire( UnityPlayer, new Distance::Events.RaceMode.FinalCountdownActivate.Data(value, (int)(value - Server.ModeTime + 0.5)) ); } } Countdown = value; }
public void Update() { if (Finished) { return; } if (Plugin.ServerStage != BasicAutoServer.Stage.Started) { return; } var playersInMode = GetModePlayers(); if (playersInMode.Count <= 1) { IsInSinglePlayerMode = true; MaxModeTime += UnityEngine.Time.deltaTime; } else if (IsInSinglePlayerMode) { IsInSinglePlayerMode = false; // When transitioning out of single-player mode, give the bubble to the new player to reset the timer: if (TaggedPlayer != null) { var nonTagged = playersInMode.Find((player) => TaggedPlayer != player); if (nonTagged != null) { TaggedPlayer.GetExternalData <ReverseTagData>().SecondsTagged = 0.0; DistanceServerMainStarter.Instance.StartCoroutine(GiveTagBubbleSoon(TaggedPlayer, nonTagged)); } } } if (TaggedPlayer != null && !IsPlayerInMode(TaggedPlayer)) { TagRandomLastPlacePlayer(); if (!IsPlayerInMode(TaggedPlayer)) { TagPlayer(null); } } if (TaggedPlayer != null && !IsInSinglePlayerMode) { TaggedPlayer.GetExternalData <ReverseTagData>().AddSecondsTagged(UnityEngine.Time.deltaTime, WinTime); } var leader = GetFirstPlacePlayer(); if (leader != Leader) { if (leader != null) { var colorHex = Distance::ColorEx.ColorToHexNGUI(Distance::ColorEx.PlayerRainbowColor(leader.Index)); var nameColored = $"[{colorHex}]{leader.Name}[-]"; var chat = DistanceChat.Server("Vanilla:TakenTheLead", $"{nameColored} has taken the lead!"); chat.ChatType = DistanceChat.ChatTypeEnum.ServerVanilla; Plugin.Server.SayChat(chat); } Leader = leader; } var leaderSecondsTagged = Leader == null ? 0.0 : Leader.GetExternalData <ReverseTagData>().SecondsTagged; if (leaderSecondsTagged >= WinTime || Plugin.Server.ModeTime >= MaxModeTime) { Finished = true; if (Leader != null) { var networkFinishedData = new Distance::Events.ReverseTag.Finished.Data(Leader.Index, leaderSecondsTagged); DistanceServerMain.GetEvent <Events.ServerToClient.ReverseTagFinished>().Fire(UnityEngine.RPCMode.Others, networkFinishedData); } Log.Debug($"Advancing level because win condition met: {leaderSecondsTagged} >= {WinTime} || {Plugin.Server.ModeTime} > {MaxModeTime}"); Plugin.AdvanceLevel(); } if (Finished) { return; } AdvanceLevelIfOnlyFinishedPlayers(); var secondsLeft = Math.Max(0.0, Math.Min(WinTime - leaderSecondsTagged, MaxModeTime - Plugin.Server.ModeTime)); if (secondsLeft <= 30 && !HasShown30SecondWarning) { HasShown30SecondWarning = true; var colorHex = Distance::ColorEx.ColorToHexNGUI(Distance::Colors.orangeRed); var chat = DistanceChat.Server("Vanilla:TimeWarning", $"[{colorHex}]30 seconds left![-]"); chat.ChatType = DistanceChat.ChatTypeEnum.ServerVanilla; Plugin.Server.SayChat(chat); } else if (secondsLeft <= 10 && !HasShown10SecondWarning) { HasShown10SecondWarning = true; var colorHex = Distance::ColorEx.ColorToHexNGUI(Distance::Colors.orangeRed); var chat = DistanceChat.Server("Vanilla:TimeWarning", $"[{colorHex}]10 seconds left![-]"); chat.ChatType = DistanceChat.ChatTypeEnum.ServerVanilla; Plugin.Server.SayChat(chat); } }
public override void Start() { ReadSettings(); Log.Info($"Starting HTTP Info Server on port {Port}"); worker = new ThreadWorker <RequestInfo>(); worker.QueueResponses = false; Server.OnUpdateEvent.Connect(() => { worker.Respond(info => { info.Request.Respond(); return(info.Request); }); }); var listener = new HttpListener(); Server.OnDestroyEvent.Connect(() => { listener.Abort(); }); listener.Prefixes.Add($"http://*:{Port}/"); if (PortHttps >= 0 && PortHttps != Port) { listener.Prefixes.Add($"https://*:{PortHttps}/"); } listener.Start(); listener.BeginGetContext(listenerCallback, listener); Log.Debug($"Started HTTP(S) Info Server on port {Port}"); DistanceServerMain.GetEvent <Events.ClientToAllClients.ChatMessage>().Connect((data, info) => { var playerMatch = Regex.Match(data.message_, @"^\[[0-9A-F]{6}\](.*?)\[FFFFFF\]: (.*)$"); if (!playerMatch.Success) { return; } var playerName = Regex.Replace(playerMatch.Groups[1].ToString(), @"\[.*\]", "").ToLower(); var player = Server.ValidPlayers.Find(distPlayer => distPlayer.Name.ToLower() == Regex.Replace(playerMatch.Groups[1].ToString(), @"\[.*\]", "").ToLower()); if (player == null) { return; } var message = playerMatch.Groups[2].ToString(); Match match; match = Regex.Match(message, @"^/unlink$"); if (match.Success) { var keysToRemove = new List <string>(); foreach (var pair in Links) { if (pair.Value == player.UnityPlayerGuid) { keysToRemove.Add(pair.Key); } } foreach (var key in keysToRemove) { Links.Remove(key); } Server.SayLocalChat(player.UnityPlayer, DistanceChat.Server("HttpServer:Link", $"Your game session has been unlinked from {keysToRemove.Count} web session{(keysToRemove.Count == 1 ? "s" : "")}")); return; } match = Regex.Match(message, @"^/link (\w{6})$"); if (match.Success) { var code = match.Groups[1].ToString().ToUpper(); if (!CodesReverse.ContainsKey(code)) { var add = ""; if (HelpTextWebsite != null) { add = $"\nVisit {HelpTextWebsite.Replace("$linkcode", GetOrGenerateCode(player.UnityPlayerGuid))} to view and vote online."; } Server.SayLocalChat(player.UnityPlayer, DistanceChat.Server("HttpServer:Link", "Invalid link code!" + add)); } Links[CodesReverse[code]] = player.UnityPlayerGuid; CodesReverse.Remove(code); Server.SayLocalChat(player.UnityPlayer, DistanceChat.Server("HttpServer:Link", $"Your game session has been linked to a web session!\nType [00FFFF]/unlink[-] to undo this.")); return; } match = Regex.Match(message, @"^/link"); if (match.Success) { if (HelpTextWebsite != null) { Server.SayLocalChat(player.UnityPlayer, DistanceChat.Server("HttpServer:Link", $"Visit {HelpTextWebsite.Replace("$linkcode", GetOrGenerateCode(player.UnityPlayerGuid))} to view and vote online.")); } return; } }); Manager.Server.OnPlayerValidatedEvent.Connect(player => { GetOrGenerateCode(player.UnityPlayerGuid); }); var autoServer = Manager.GetPlugin <BasicAutoServer.BasicAutoServer>(); if (autoServer != null) { Log.Debug("Set LinkCodeGetter in BasicAutoServer"); autoServer.LinkCodeGetter = player => { return(GetOrGenerateCode(player.UnityPlayerGuid)); }; } Manager.Server.OnPlayerDisconnectedEvent.Connect(player => { Expiry[player.UnityPlayerGuid] = DistanceServerMain.UnixTime + 5 * 60; string keyToRemove = null; foreach (var pair in CodesForward) { if (pair.Value == player.UnityPlayerGuid) { keyToRemove = pair.Key; break; } } if (keyToRemove != null) { CodesForward.Remove(keyToRemove); } }); double lastUpdate = 0; Manager.Server.OnUpdateEvent.Connect(() => { var now = DistanceServerMain.UnixTime; if (now - lastUpdate >= 60) { lastUpdate = now; var KeysToRemove = new List <string>(); foreach (var pair in Links) { if (IsExpired(pair.Key, now) || IsExpired(pair.Value, now)) { KeysToRemove.Add(pair.Key); } } foreach (var key in KeysToRemove) { Links.Remove(key); } KeysToRemove.Clear(); foreach (var pair in CodesForward) { if (IsExpired(pair.Value, now)) { KeysToRemove.Add(pair.Key); } } foreach (var key in KeysToRemove) { CodesForward.Remove(key); } KeysToRemove.Clear(); foreach (var pair in CodesReverse) { if (IsExpired(pair.Value, now)) { KeysToRemove.Add(pair.Key); } } foreach (var key in KeysToRemove) { CodesReverse.Remove(key); } } }); Log.Debug($"Started handling code linking"); }
public override void Start() { Log.Info("Basic Auto Server started!"); Playlist.AddRange(OfficialPlaylist); Filters = new List <FilterWorkshopSearchDelegate>(); ReadSettings(); UnityEngine.MasterServer.dedicatedServer = ReportToMasterServerAsDedicatedServer; Server.MasterServerGameModeOverride = MasterServerGameModeOverride; Server.ServerName = ServerName; Server.MaxPlayers = MaxPlayers; Server.Port = Port; Server.UseNat = UseNat; if (ReportToMasterServerInitialDelay > 0) { Server.ReportToMasterServer = false; DistanceServerMainStarter.Instance.StartCoroutine(SetReportToMasterServerAfterDelay()); } else { Server.ReportToMasterServer = ReportToMasterServer; } lastMasterServerRegistration = DistanceServerMain.UnixTime; if (PrivateServerPassword != null) { UnityEngine.Network.incomingPassword = PrivateServerPassword; } Server.OnPlayerConnectedEvent.Connect(player => { player.Countdown = CountdownTime; player.OnCarAddedEvent.Connect(car => { car.AddExternalData(new LastMoveTimeData(DistanceServerMain.UnixTime)); OnCarAddedEvent.Fire(car); }); }); if (WelcomeMessage != null) { Server.OnPlayerValidatedEvent.Connect(player => { var message = WelcomeMessage; if (message.Contains("$linkcode") && LinkCodeGetter != null) { message = message.Replace("$linkcode", LinkCodeGetter(player)); } message = message.Replace("$player", player.Name); if (!Server.HasModeStarted || player.Car != null) { Server.SayLocalChat(player.UnityPlayer, DistanceChat.Server("AutoServer:Welcome", message)); } else { IEventConnection connection = null; connection = player.OnCarAddedEvent.Connect(car => { Server.SayLocalChat(player.UnityPlayer, DistanceChat.Server("AutoServer:Welcome", message)); connection.Disconnect(); }); } }); } Server.OnLevelStartedEvent.Connect(() => { CountdownTime = -1.0; }); Server.OnModeStartedEvent.Connect(() => { StartingPlayerGuids.Clear(); foreach (var player in Server.ValidPlayers) { if (player.Car != null) { player.Car.GetExternalData <LastMoveTimeData>().LastMoveTime = DistanceServerMain.UnixTime; SetStartingPlayer(player.UnityPlayerGuid, true); } } if (ServerStage == Stage.Starting) { ServerStage = Stage.Started; } }); OnAdvancingToNextLevel.Connect(() => { if (TipMessages.Count > 0) { var tip = TipMessages[currentTip]; currentTip = (currentTip + 1) % TipMessages.Count; Server.SayChat(DistanceChat.Server("AutoServer:Tip", tip)); } }); DistanceServerMain.GetEvent <Events.Instanced.Finished>().Connect((instance, data) => { Log.WriteLine($"{((DistanceCar)instance).Player.Name} finished"); AttemptToAdvanceLevel(); }); if (LoadWorkshopLevels) { DistanceServerMainStarter.Instance.StartCoroutine(DoLoadWorkshopLevels()); } else { StartAutoServer(); } }
/// public void Init() { DistanceServerMain.GetEvent <Events.ClientToServer.SubmitPlayerInfo>().Connect((data, info) => { // ignore data.sender_, it should be sender var player = GetDistancePlayer(info.sender); player.Name = data.playerName_; player.ReceivedInfo = true; player.Index = ValidPlayers.Count; player.ValidatedAt = DistanceServerMain.UnixTime; ValidPlayers.Add(player); player.OnValidatedPreReplicationEvent.Fire(); OnPlayerValidatedPreReplicationEvent.Fire(player); DistanceServerMain.GetEvent <Events.ServerToClient.AddClient>().Fire( RPCMode.Others, player.GetAddClientData(true) ); player.OnValidatedEvent.Fire(); OnPlayerValidatedEvent.Fire(player); }); DistanceServerMain.GetEvent <Events.ClientToServer.CompletedRequest>().Connect((data, info) => { // ignore data.networkPlayer_, it should be sender var distancePlayer = GetDistancePlayer(info.sender); if (data.request_ == Distance::ServerRequest.SubmitClientInfo) // TODO: check if request was actually completed for security { distancePlayer.State = DistancePlayer.PlayerState.Initialized; SendPlayerToCurrentLocation(data.networkPlayer_); } else if (data.request_ == Distance::ServerRequest.LoadLobbyScene) { distancePlayer.Stuck = false; distancePlayer.State = DistancePlayer.PlayerState.LoadedLobbyScene; SendLobbyServerInfo(data.networkPlayer_); SendLevelInfo(data.networkPlayer_); RequestLevelCompatibilityInfo(data.networkPlayer_); RequestSubmitLobbyInfo(data.networkPlayer_); if (!IsInLobby) { distancePlayer.State = DistancePlayer.PlayerState.CantLoadLevelSoInLobby; } } else if (data.request_ == Distance::ServerRequest.SubmitLobbyInfo) { distancePlayer.State = DistancePlayer.PlayerState.SubmittedLobbyInfo; } else if (data.request_ == Distance::ServerRequest.LoadGameModeScene) { distancePlayer.Stuck = false; distancePlayer.State = DistancePlayer.PlayerState.LoadedGameModeScene; if (distancePlayer.LevelId != CurrentLevelId) { SendPlayerToLevel(distancePlayer.UnityPlayer); return; } // fire CreatePlayer for sender for all existing cars (see WelcomeClientToGameMode.Data) foreach (var player in ValidPlayers) { if (player.Car != null) { DistanceServerMain.GetEvent <Events.ServerToClient.CreatePlayer>().Fire( data.networkPlayer_, new Distance::Events.ServerToClient.CreatePlayer.Data(player.Car.GetPlayerInitializeData(), player.Car.GetPlayerLateInitializeData(), player.Index) ); if (!player.Car.Finished && player.Car.Alive) { var gameObject = player.Car.Networker; var transform = gameObject.transform; DistanceServerMain.GetEvent <Events.ServerToClient.CreateExistingCar>().Fire( data.networkPlayer_, new Distance::Events.ServerToClient.CreateExistingCar.Data(transform.position, transform.rotation, player.Car.WingsOpen, player.Index) ); } } } if (HasModeStarted) { // TODO: sync game mode things if already started -- different for every game mode (see SyncLateClientToGameMode.Data and SyncMode.Data) // NOTE: this should be handled entirely by the game mode programming, not by the base server programming OnNeedToSyncLateClientToGameMode.Fire(distancePlayer); if (distancePlayer.Countdown != -1.0) { DistanceServerMain.GetEvent <Events.ServerToClient.FinalCountdownActivate>().Fire( data.networkPlayer_, new Distance::Events.RaceMode.FinalCountdownActivate.Data(distancePlayer.Countdown, (int)(distancePlayer.Countdown - ModeTime)) ); } } RequestSubmitGameModeInfo(data.networkPlayer_); } else if (data.request_ == Distance::ServerRequest.SubmitGameModeInfo) { distancePlayer.State = DistancePlayer.PlayerState.SubmittedGameModeInfo; // If mode has not started, try to start it (check if all players have submitted info/loaded) // If mode has started, set state to StartedMode and fire StartClientLate // (see ServerLogic.OnEventCompletedRequest) if (StartingMode) { AttemptToStartMode(); } else { distancePlayer.State = DistancePlayer.PlayerState.StartedMode; DistanceServerMain.GetEvent <Events.ServerToClient.StartMode>().Fire( data.networkPlayer_, new Distance::Events.ServerToClient.StartMode.Data(ModeStartTime, true) ); } } }); DistanceServerMain.GetEvent <Events.ClientToAllClients.ChatMessage>().Connect((data, info) => { var chatTypeData = new Tuple <DistanceChat.ChatTypeEnum, string>(DistanceChat.ChatTypeEnum.Unknown, "Unknown"); var distancePlayer = GetDistancePlayer(info.sender); if (distancePlayer != null && distancePlayer.Valid) { chatTypeData = DistanceChat.DeduceChatType(data.message_, distancePlayer.Name); } var chat = new DistanceChat(data.message_) { SenderGuid = info.sender.guid, ChatType = chatTypeData.Item1, ChatDescription = chatTypeData.Item2, }; AddChat(chat); }); DistanceServerMain.GetEvent <Events.ClientToAllClients.SetReady>().Connect((data, info) => { // ignore data.player_, it should be sender GetDistancePlayer(info.sender).Ready = data.ready_; }); DistanceServerMain.GetEvent <Events.ClientToServer.SubmitLevelCompatabilityInfo>().Connect((data, info) => { // ignore data.player_, it should be sender var distancePlayer = GetDistancePlayer(info.sender); distancePlayer.LevelCompatibilityInfo = new LevelCompatibilityInfo(data); Log.Debug($"Level compatibility versions test: {data.levelVersion_} : {CurrentLevel.LevelVersion}"); // TODO: write proper level compat check code (the current computed version is incorrect, so version checking is ignored) DistanceServerMain.GetEvent <Events.ServerToClient.UpdatePlayerLevelCompatibilityStatus>().Fire( data.player_, new Distance::Events.ServerToClient.UpdatePlayerLevelCompatibilityStatus.Data(info.sender, distancePlayer.LevelCompatability) ); if (distancePlayer.State == DistancePlayer.PlayerState.WaitingForCompatibilityStatus) { SendPlayerToLevel(distancePlayer.UnityPlayer); } }); DistanceServerMain.GetEvent <Events.ClientToServer.SubmitPlayerData>().Connect((data, info) => { // ignore data.player_, it should be sender var distancePlayer = GetDistancePlayer(info.sender); distancePlayer.RestartTime = -1.0; distancePlayer.Car = new DistanceCar(distancePlayer, data.data_); distancePlayer.Car.MakeNetworker(); DistanceServerMain.GetEvent <Events.ServerToClient.CreatePlayer>().Fire( RPCMode.Others, new Distance::Events.ServerToClient.CreatePlayer.Data(distancePlayer.Car.GetPlayerInitializeData(), distancePlayer.Car.GetPlayerLateInitializeData(), distancePlayer.Index) ); }); }