예제 #1
0
        private static async Task PrepareReplay(Game.StartProperties properties, IGameUi ui, CancellationToken cancellation)
        {
            var replayProperties = properties.ReplayProperties;

            if (replayProperties != null)
            {
                var replayFilename = replayProperties.Filename ?? Path.Combine(AcPaths.GetReplaysDirectory(), replayProperties.Name);
                ui.OnProgress("Checking replay for fake cars…");

                var fakes = await FakeCarsHelper.GetFakeCarsIds(replayFilename);

                if (fakes.Count > 0)
                {
                    Logging.Debug("Fakes found: " + fakes.Select(x => $"{x.FakeId} ({x.SourceId})").JoinToString(", "));
                    foreach (var fake in fakes)
                    {
                        var car = CarsManager.Instance.GetById(fake.SourceId);
                        if (car != null)
                        {
                            FakeCarsHelper.CreateFakeCar(car, fake.FakeId, null);
                        }
                        else
                        {
                            Logging.Warning("Original not found: " + fake.SourceId);
                        }
                    }
                }
            }
        }
예제 #2
0
        void IGameUi.Show(Game.StartProperties properties)
        {
            _properties = properties;

            ShowDialogWithoutBlocking();
            Model.WaitingStatus = AppStrings.Race_Initializing;
        }
예제 #3
0
        private static void PrepareRaceDriverName(Game.StartProperties properties)
        {
            if (properties.HasAdditional <SrsMark>())
            {
                return;
            }

            if (properties.BasicProperties?.DriverName != null)
            {
                properties.SetAdditional(new DriverName(properties.BasicProperties.DriverName, properties.BasicProperties.DriverNationality));
                return;
            }

            if (properties.ModeProperties is Game.OnlineProperties online && SettingsHolder.Live.SrsEnabled && SettingsHolder.Live.SrsAutoMode)
            {
                var filter = Filter.Create(new StringTester(), SettingsHolder.Live.SrsAutoMask, true);
                if (filter.Test(online.ServerName ?? ""))
                {
                    Logging.Write("Looks like this is a SRS server, let’s use SRS name");
                    properties.SetAdditional(new SrsMark {
                        Name        = SrsMark.GetName(),
                        Nationality = "",
                        Team        = ""
                    });
                    return;
                }
            }

            properties.SetAdditional(new DriverName());
        }
예제 #4
0
 private static void PrepareRaceModeImmediateStart(Game.StartProperties properties)
 {
     if (!SettingsHolder.Drive.ImmediateStart)
     {
         return;
     }
     properties.SetAdditional(new ImmediateStart());
 }
예제 #5
0
        private static IAcsStarter CreateStarter(Game.StartProperties properties)
        {
            var starter = AcsStarterFactory.Create();

            if (SettingsHolder.Drive.PatchAcToDisableShadows && AcShadowsPatcher.IsSupposedToWork())
            {
                properties.SetAdditional(new AcShadowsPatcher(starter));
            }

            return(starter);
        }
예제 #6
0
 private static void StartAsync_AdjustProperties(Game.StartProperties properties)
 {
     if (SettingsHolder.Integrated.RsrLimitTemperature && properties.ConditionProperties != null &&
         (properties.ConditionProperties.AmbientTemperature < 10d || properties.ConditionProperties.RoadTemperature < 10d) &&
         AcSettingsHolder.Python.IsActivated("RsrLiveTime"))
     {
         Toast.Show("Temperature Set To 10 °C", "RSR is active, and according to its rules, you are not allowed to use temperatures lower than 10 °C");
         properties.ConditionProperties.AmbientTemperature = 10d;
         properties.ConditionProperties.RoadTemperature    = 10d;
     }
 }
예제 #7
0
        private static void StartAsync_Prepare(Game.StartProperties properties)
        {
            if (!_nationCodesProviderSet)
            {
                _nationCodesProviderSet = true;
                try {
                    Game.NationCodeProvider = NationCodeProvider.Instance;
                } catch (Exception e) {
                    Logging.Unexpected(e);
                }
            }

            AcSettingsHolder.Graphics.FixShadowMapBias();

            if (SettingsHolder.Drive.CopyFilterToSystemForOculus && AcSettingsHolder.Video.CameraMode.Id == "OCULUS")
            {
                properties.SetAdditional(new CopyFilterToSystemForOculusHelper());
            }

            if (SettingsHolder.Common.FixResolutionAutomatically)
            {
                Logging.Debug("Trying to fix resolution just in case…");
                AcSettingsHolder.Video.EnsureResolutionIsCorrect();
            }

            if (SettingsHolder.Drive.WeatherSpecificClouds)
            {
                properties.SetAdditional(new WeatherSpecificCloudsHelper());
            }

            if (SettingsHolder.Drive.WeatherSpecificTyreSmoke)
            {
                properties.SetAdditional(new WeatherSpecificTyreSmokeHelper());
            }

            if (SettingsHolder.Live.RsrEnabled && SettingsHolder.Live.RsrDisableAppAutomatically)
            {
                PrepareRaceModeRsr(properties);
            }

            if (SettingsHolder.Drive.SidekickIntegration && properties.BasicProperties?.CarId != null)
            {
                SidekickHelper.UpdateSidekickDatabase(properties.BasicProperties.CarId);
            }

            if (SettingsHolder.Drive.RaceEssentialsIntegration && properties.BasicProperties?.CarId != null)
            {
                RaceEssentialsHelper.UpdateRaceEssentialsDatabase(properties.BasicProperties.CarId, false);
            }

            properties.SetAdditional(new WeatherSpecificVideoSettingsHelper());
            properties.SetAdditional(new ModeSpecificPresetsHelper());
            properties.SetAdditional(new CarSpecificControlsPresetHelper());
        }
예제 #8
0
        private static void PrepareRaceModeRsr(Game.StartProperties properties)
        {
            var rsrMode = properties.GetAdditional <RsrMark>() != null;
            var form    = AcSettingsHolder.Forms.Entries.GetByIdOrDefault(RsrMark.FormId);

            if (form != null)
            {
                form.SetVisibility(rsrMode);
                AcSettingsHolder.Forms.SaveImmediately();
            }
        }
예제 #9
0
        private static void StartAsync_PrepareRace(Game.StartProperties properties)
        {
            if (properties.AssistsProperties == null)
            {
                properties.AssistsProperties = _defaultAssistsFactory?.Create();
            }

            PrepareRaceModeImmediateStart(properties);
            PrepareRaceDriverName(properties);

            Logging.Write("Assists: " + properties.AssistsProperties?.GetDescription());
        }
예제 #10
0
        internal ReplayHelper(Game.StartProperties startProperties, Game.Result result)
        {
            OriginalFilename = Path.Combine(FileUtils.GetReplaysDirectory(), ReplayObject.PreviousReplayName);
            RenamedFilename  = FileUtils.EnsureUnique(OriginalFilename);
            Name             = GetReplayName(startProperties, result);

            IsAvailable = File.Exists(OriginalFilename);
            if (IsAvailable && SettingsHolder.Drive.AutoSaveReplays)
            {
                IsRenamed = true;
            }
        }
예제 #11
0
        private static Task <Game.Result> StartAsync(Game.StartProperties properties, GameMode mode)
        {
            StartAsync_AdjustProperties(properties);
            StartAsync_Prepare(properties);

            if (mode == GameMode.Race)
            {
                StartAsync_PrepareRace(properties);
            }

            return(_uiFactory == null?StartAsync_NoUi(properties, mode) : StartAsync_Ui(properties, mode));
        }
예제 #12
0
        private static Task <Game.Result> StartAsync(Game.StartProperties properties, GameMode mode)
        {
            StartAsync_Prepare(properties);
            // properties.SetAdditional(new FocusHelper());

            if (mode == GameMode.Race)
            {
                StartAsync_PrepareRace(properties);
            }

            return(_uiFactory == null?StartAsync_NoUi(properties, mode) : StartAsync_Ui(properties, mode));
        }
예제 #13
0
        public void Show(Game.StartProperties properties, GameMode mode)
        {
            _properties = properties;
            _mode       = mode;

            ShowDialogAsync().Forget();
            Model.WaitingStatus = AppStrings.Race_Initializing;

            if (SettingsHolder.Drive.WatchForSharedMemory &&
                (SettingsHolder.Drive.MonitorFramesPerSecond || mode == GameMode.Benchmark || mode == GameMode.Replay && OptionBenchmarkReplays))
            {
                AcSharedMemory.Instance.MonitorFramesPerSecond = true;
            }
        }
예제 #14
0
        public GameDiscordPresence(Game.StartProperties properties, GameMode mode)
        {
            switch (mode)
            {
            case GameMode.Replay:
                _presence = new DiscordRichPresence(1000, "Preparing to race", "Watching replay");
                break;

            case GameMode.Benchmark:
                _presence = new DiscordRichPresence(1000, "Preparing to race", "Running benchmark");
                break;

            case GameMode.Race:
                if (properties.GetAdditional <RsrMark>() != null)
                {
                    _presence = new DiscordRichPresence(1000, "RSR", "Hotlap");
                }
                else if (properties.GetAdditional <SrsMark>() != null)
                {
                    _presence = new DiscordRichPresence(1000, "SRS", "In a race");
                }
                else if (properties.GetAdditional <WorldSimSeriesMark>() != null)
                {
                    _presence = new DiscordRichPresence(1000, "WSS", "In a race");
                }
                else if (properties.ModeProperties is Game.OnlineProperties online)
                {
                    _presence = new DiscordRichPresence(1000, "Online", "In a race");
                    WatchForOnlineDetails(online).Ignore();
                }
                else if (properties.GetAdditional <SpecialEventsManager.EventProperties>()?.EventId is string challengeId)
                {
                    var challenge = SpecialEventsManager.Instance.GetById(challengeId);
                    _presence = new DiscordRichPresence(1000, "Driving Solo", challenge != null ? $"Challenge | {challenge.DisplayName}" : "Challenge");
                }
                else
                {
                    _presence = new DiscordRichPresence(1000, "Driving Solo", GetSessionName(properties.ModeProperties));
                }
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(mode), mode, null);
            }

            _presence.Now()
            .Car(properties.BasicProperties?.CarId)
            .Track(properties.BasicProperties?.TrackId, properties.BasicProperties?.TrackConfigurationId);
        }
예제 #15
0
        private static async Task <Game.Result> StartAsync_NoUi(Game.StartProperties properties, GameMode mode)
        {
            using (ReplaysExtensionSetter.OnlyNewIfEnabled())
                using (ScreenshotsConverter.OnlyNewIfEnabled()) {
                    if (mode == GameMode.Race)
                    {
                        properties.SetAdditional(new RaceCommandExecutor(properties));
                    }
                    else if (mode == GameMode.Replay)
                    {
                        properties.SetAdditional(new ReplayCommandExecutor(properties));
                    }

                    return(await Game.StartAsync(AcsStarterFactory.Create(), properties, null, CancellationToken.None));
                }
        }
예제 #16
0
        private static string GetReplayName([CanBeNull] Game.StartProperties startProperties, [CanBeNull] Game.Result result)
        {
            if (startProperties == null)
            {
                return($"_autosave_{DateTime.Now.ToMillisecondsTimestamp()}.acreplay");
            }

            var s = SettingsHolder.Drive.ReplaysNameFormat;

            if (string.IsNullOrEmpty(s))
            {
                s = SettingsHolder.Drive.DefaultReplaysNameFormat;
            }

            return(FileUtils.EnsureFileNameIsValid(VariablesReplacement.Process(s, startProperties, result)));
        }
예제 #17
0
        public void AddNewResult([NotNull] Game.StartProperties startProperties, [NotNull] Game.Result result)
        {
            var directory = SessionsDirectory;

            FileUtils.EnsureDirectoryExists(directory);

            var fileName = DateTime.Now.ToString("yyMMdd-HHmmss") + ".json";
            var raceOut  = AcPaths.GetResultJsonFilename();

            JObject data = null;

            if (File.Exists(raceOut))
            {
                try {
                    // Let’s try to save original data instead in case we missed something during parsing.
                    // But let’s remove formatting just in case.
                    data = JObject.Parse(File.ReadAllText(raceOut));
                } catch (Exception e) {
                    Logging.Warning(e);
                }
            }

            if (data == null)
            {
                data = JObject.FromObject(result);
            }

            // Trying to keep race params as well…
            // TODO: Do it the other way around, from start params?

            var raceIni = AcPaths.GetRaceIniFilename();

            if (File.Exists(raceIni))
            {
                data[KeyRaceIni] = File.ReadAllText(raceIni);
            }

            var quickDrive = startProperties.GetAdditional <QuickDrivePresetProperty>();

            if (quickDrive?.SerializedData != null)
            {
                data[KeyQuickDrive] = quickDrive.SerializedData;
            }

            File.WriteAllText(FileUtils.EnsureUnique(Path.Combine(directory, fileName)), data.ToString(Formatting.None));
        }
예제 #18
0
        public static string Process([NotNull] string str, [NotNull] Game.StartProperties startProperties, [CanBeNull] Game.Result result)
        {
            if (startProperties == null)
            {
                throw new ArgumentNullException(nameof(startProperties));
            }
            if (str == null)
            {
                throw new ArgumentNullException(nameof(str));
            }

            return(ReplayNameRegex.Replace(str, match => {
                var value = GetValue(startProperties, result, match.Groups[1].Value)?.Trim();
                if (string.IsNullOrEmpty(value))
                {
                    return "-";
                }

                foreach (var c in match.Groups[2].Success ? match.Groups[2].Value.ToLowerInvariant() : string.Empty)
                {
                    switch (c)
                    {
                    case 'l':
                        value = value.ToLowerInvariant();
                        break;

                    case 'u':
                        value = value.ToUpperInvariant();
                        break;

                    case '0':
                        value = value.Substring(0, 1);
                        break;

                    default:
                        Logging.Warning("Unsupported modifier: " + c);
                        break;
                    }
                }

                return value;
            }));
        }
예제 #19
0
        async void IGameUi.Show(Game.StartProperties properties)
        {
            _resultShown = false;

            if (Model.Renderer != null)
            {
                Model.Renderer.SetCameraHigher = false;
            }

            await Task.Delay(1000);

            ProgressBar.Visibility     = Visibility.Visible;
            LoadingText.Visibility     = Visibility.Collapsed;
            PlayerNamePanel.Visibility = Visibility.Collapsed;
            GameResultOk.Visibility    = Visibility.Hidden;
            LoadingPanel.SetValue(VisibilityAnimation.VisibleProperty, true);

            await Task.Delay(2000);

            DisableRenderer();
        }
예제 #20
0
        public static string GetType(Game.StartProperties startProperties, [CanBeNull] Game.Result result)
        {
            // TODO: drag mode
            if (startProperties.ModeProperties is Game.DriftProperties)
            {
                return("Drift");
            }

            if (startProperties.ModeProperties is Game.TimeAttackProperties)
            {
                return("Time Attack");
            }

            if (startProperties.ModeProperties is Game.HotlapProperties)
            {
                return("Hotlap");
            }

            if (startProperties.ModeProperties is Game.OnlineProperties)
            {
                return("Online");
            }

            if (startProperties.ModeProperties is Game.PracticeProperties)
            {
                return("Practice");
            }

            if (result?.Sessions?.Length == 1)
            {
                return("Race");
            }

            if (result?.Sessions?.Length > 1)
            {
                return("Weekend");
            }

            return(startProperties.ModeProperties is Game.RaceProperties ? "Race" : "Something Unspeakable");
        }
예제 #21
0
        private static string GetValue(Game.StartProperties startProperties, [CanBeNull] Game.Result result, string key)
        {
            if (startProperties.BasicProperties == null)
            {
                return(null);
            }

            switch (key)
            {
            case "type":
                return(GetType(startProperties, result));

            case "car":
                return(CarsManager.Instance.GetById(startProperties.BasicProperties.CarId)?.DisplayName);

            case "car.id":
                return(startProperties.BasicProperties.CarId);

            case "track":
                var track  = TracksManager.Instance.GetById(startProperties.BasicProperties.TrackId);
                var config = startProperties.BasicProperties.TrackConfigurationId != null
                            ? track?.GetLayoutByLayoutId(startProperties.BasicProperties.TrackConfigurationId) : track;

                return(config?.Name);

            case "track.id":
                return(startProperties.BasicProperties.TrackId);

            case "date":
                return(startProperties.StartTime.ToString(CultureInfo.CurrentCulture));

            case "date_ac":
                return(GetAcDate(startProperties.StartTime));

            default:
                return(null);
            }
        }
예제 #22
0
 public GameStartedArgs([NotNull] Game.StartProperties startProperties) {
     StartProperties = startProperties;
 }
예제 #23
0
        private async Task Join(object o) {
            var carEntry = CarsView?.CurrentItem as CarEntry;
            if (carEntry == null) return;

            var carId = carEntry.CarObject.Id;
            var correctId = CarIds.FirstOrDefault(x => string.Equals(x, carId, StringComparison.OrdinalIgnoreCase));

            if (BookingMode && !ReferenceEquals(o, ActualJoin) && !ReferenceEquals(o, ForceJoin)) {
                if (_factory == null) {
                    Logging.Error("Booking: UI factory is missing");
                    return;
                }

                PrepareBookingUi();
                ProcessBookingResponse(await Task.Run(() => KunosApiProvider.TryToBook(Ip, PortC, Password, correctId, carEntry.AvailableSkin?.Id,
                        DriverName.GetOnline(), "")));
                return;
            }

            DisposeHelper.Dispose(ref _ui);
            IsBooked = false;
            BookingErrorMessage = null;

            var properties = new Game.StartProperties(new Game.BasicProperties {
                CarId = carId,
                CarSkinId = carEntry.AvailableSkin?.Id,
                TrackId = Track?.Id,
                TrackConfigurationId = Track?.LayoutId
            }, null, null, null, new Game.OnlineProperties {
                RequestedCar = correctId,
                ServerIp = Ip,
                ServerName = DisplayName,
                ServerPort = PortT,
                ServerHttpPort = PortC,
                Guid = SteamIdHelper.Instance.Value,
                Password = Password
            });

            await GameWrapper.StartAsync(properties);
            var whatsGoingOn = properties.GetAdditional<AcLogHelper.WhatsGoingOn>();
            WrongPassword = whatsGoingOn?.Type == AcLogHelper.WhatsGoingOnType.OnlineWrongPassword;
            if (whatsGoingOn == null) RecentManager.Instance.AddRecentServer(OriginalInformation);
        }
예제 #24
0
 public static Task <Game.Result> StartAsync(Game.StartProperties properties)
 {
     return(StartAsync(properties, GameMode.Race));
 }
예제 #25
0
 public static Task StartReplayAsync(Game.StartProperties properties)
 {
     return(StartAsync(properties, GameMode.Replay));
 }
예제 #26
0
 public static Task StartBenchmarkAsync(Game.StartProperties properties)
 {
     return(StartAsync(properties, GameMode.Benchmark));
 }
예제 #27
0
        private static async Task <Game.Result> StartAsync_Ui(Game.StartProperties properties, GameMode mode)
        {
            using (var ui = _uiFactory.Create()) {
                Logging.Write($"Starting game: {properties.GetDescription()}");
                ui.Show(properties, mode);

                CancellationTokenSource linked = null;
                IsInGame = true;

                try {
                    Game.Result result;
                    using (ReplaysExtensionSetter.OnlyNewIfEnabled())
                        using (ScreenshotsConverter.OnlyNewIfEnabled()) {
                            Started?.Invoke(null, new GameStartedArgs(properties, mode));

                            if (mode == GameMode.Race)
                            {
                                properties.SetAdditional(new RaceCommandExecutor(properties));
                                properties.SetAdditional(new DBoxIntegration());
                                if (SettingsHolder.Drive.ContinueOnEscape)
                                {
                                    properties.SetAdditional(new ContinueRaceHelper());
                                }
                            }
                            else if (mode == GameMode.Replay)
                            {
                                properties.SetAdditional(new ReplayCommandExecutor(properties));
                            }

                            var cancellationToken = ui.CancellationToken;
                            if (SettingsHolder.Drive.ImmediateCancel)
                            {
                                var cancelHelper = new ImmediateCancelHelper();
                                linked            = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, cancelHelper.GetCancellationToken());
                                cancellationToken = linked.Token;
                                properties.SetAdditional(cancelHelper);
                                properties.SetKeyboardListener = true;
                            }

                            if (mode == GameMode.Replay)
                            {
                                await PrepareReplay(properties, ui, cancellationToken);
                            }

                            ui.OnProgress("Loading data for Custom Shaders Patch…");
                            var trackId = string.IsNullOrWhiteSpace(properties.BasicProperties?.TrackConfigurationId)
                                ? properties.BasicProperties?.TrackId
                                : properties.BasicProperties?.TrackId + @"/" + properties.BasicProperties?.TrackConfigurationId;
                            await PatchTracksDataUpdater.Instance.TriggerAutoLoadAsync(trackId);

                            await PatchTracksVaoDataUpdater.Instance.TriggerAutoLoadAsync(trackId);

                            await PatchBackgroundDataUpdater.Instance.TriggerAutoLoadAsync(trackId);

                            await PatchCarsDataUpdater.Instance.TriggerAutoLoadAsync(properties.BasicProperties?.CarId);

                            result = await Game.StartAsync(CreateStarter(properties), properties, new ProgressHandler(ui), cancellationToken);
                        }

                    Logging.Write($"Result: {result?.GetDescription() ?? @"<NULL>"}");
                    if (ui.CancellationToken.IsCancellationRequested)
                    {
                        ui.OnError(new UserCancelledException());
                        return(null);
                    }

                    var whatsGoingOn = mode != GameMode.Race || result == null?AcLogHelper.TryToDetermineWhatsGoingOn() : null;

                    if (whatsGoingOn != null)
                    {
                        properties.SetAdditional(whatsGoingOn);
                    }

                    if (mode == GameMode.Race)
                    {
                        var param = new GameEndedArgs(properties, result);
                        Ended?.Invoke(null, param);
                        /* TODO: should set result to null if param.Cancel is true? */

                        var replayHelper = new ReplayHelper(properties, result);
                        (result == null || param.Cancel ? Cancelled : Finished)?.Invoke(null, new GameFinishedArgs(properties, result));

                        ui.OnResult(result, replayHelper);
                    }
                    else
                    {
                        ui.OnResult(null, null);
                    }

                    return(result);
                } catch (Exception e) when(e.IsCancelled())
                {
                    // ui.OnError(new UserCancelledException());
                    ui.OnResult(null, null);
                    return(null);
                } catch (Exception e) {
                    Logging.Warning(e);
                    ui.OnError(e);
                    return(null);
                } finally {
                    linked?.Dispose();
                    IsInGame = false;
                }
            }
        }
예제 #28
0
 public GameEndedArgs([NotNull] Game.StartProperties startProperties, [CanBeNull] Game.Result result) {
     StartProperties = startProperties;
     Result = result;
 }
예제 #29
0
 protected GameCommandExecutorBase(Game.StartProperties properties) {
     _properties = properties;
 }
예제 #30
0
        private static void StartAsync_Prepare(Game.StartProperties properties)
        {
            if (!_nationCodesProviderSet)
            {
                _nationCodesProviderSet = true;
                try {
                    Game.NationCodeProvider = NationCodeProvider.Instance;
                } catch (Exception e) {
                    Logging.Unexpected(e);
                }
            }

            AcSettingsHolder.Graphics.FixShadowMapBias();
            CarCustomDataHelper.Revert();

            if (SettingsHolder.Drive.CheckAndFixControlsOrder)
            {
                try {
                    AcSettingsHolder.Controls.FixControllersOrder();
                } catch (Exception e) {
                    VisualCppTool.OnException(e, null);
                }
            }

            if (SettingsHolder.Common.FixResolutionAutomatically)
            {
                Logging.Debug("Trying to fix resolution just in case…");
                AcSettingsHolder.Video.EnsureResolutionIsCorrect();
            }

            properties.SetAdditional(new TrackDetails());
            properties.SetAdditional(
                new WeatherProceduralHelper(properties.ConditionProperties != null && properties.ConditionProperties.RoadTemperature == null));
            properties.SetAdditional(new WeatherSpecificLightingHelper());

            if (SettingsHolder.Drive.WeatherSpecificClouds)
            {
                properties.SetAdditional(new WeatherSpecificCloudsHelper());
            }

            if (SettingsHolder.Drive.WeatherSpecificTyreSmoke)
            {
                properties.SetAdditional(new WeatherSpecificTyreSmokeHelper());
            }

            if (File.Exists(properties.GetAdditional <CustomTrackState>()?.Filename))
            {
                properties.SetAdditional(new CustomTrackPropertiesHelper(properties.GetAdditional <CustomTrackState>()?.Filename ?? string.Empty));
            }

            if (SettingsHolder.Live.RsrEnabled && SettingsHolder.Live.RsrDisableAppAutomatically)
            {
                PrepareRaceModeRsr(properties);
            }

            var carId = properties.BasicProperties?.CarId;

            if (carId != null)
            {
                if (SettingsHolder.Drive.CamberExtravaganzaIntegration)
                {
                    CamberExtravaganzaHelper.UpdateDatabase(carId);
                }

                if (SettingsHolder.Drive.SidekickIntegration)
                {
                    SidekickHelper.UpdateSidekickDatabase(carId);
                }

                if (SettingsHolder.Drive.SidekickOdometerExportValues)
                {
                    SidekickHelper.OdometerExport(carId);
                }

                if (SettingsHolder.Drive.RaceEssentialsIntegration)
                {
                    RaceEssentialsHelper.UpdateRaceEssentialsDatabase(carId, false);
                }

                if (SettingsHolder.Drive.StereoOdometerExportValues)
                {
                    StereoOdometerHelper.Export(carId);
                }

                if (PatchHelper.IsFeatureSupported(PatchHelper.FeatureNeedsOdometerValue))
                {
                    var car = CarsManager.Instance.GetById(carId);
                    if (car != null)
                    {
                        properties.SetAdditional(new DrivenDistance(car.TotalDrivenDistance));
                    }
                }
            }

            properties.SetAdditional(new ModeSpecificPresetsHelper());
            properties.SetAdditional(new WeatherSpecificVideoSettingsHelper());
            properties.SetAdditional(new CarSpecificControlsPresetHelper());
            properties.SetAdditional(new CarRaceTextures());

            if (PatchHelper.GetInstalledVersion() != null)
            {
                properties.SetAdditional(new AcPatchTrackOutline());
            }

            properties.SetAdditional(new ExtraHotkeysRaceHelper());

            if (SettingsHolder.Drive.CopyFilterToSystemForOculus &&
                (AcSettingsHolder.Video.CameraMode.Id == "OCULUS" || AcSettingsHolder.Video.CameraMode.Id == "OPENVR"))
            {
                properties.SetAdditional(new CopyFilterToSystemForOculusHelper());
            }
        }
예제 #31
0
 public GameFinishedArgs([NotNull] Game.StartProperties startProperties, Game.Result result) {
     StartProperties = startProperties;
     Result = result;
 }
예제 #32
0
 public ReplayCommandExecutor(Game.StartProperties properties) : base(properties)
 {
 }
예제 #33
0
        private async Task Join(object o)
        {
            var carEntry = SelectedCarEntry;

            if (carEntry == null || Cars == null)
            {
                return;
            }

            var correctId = GetCorrectId(carEntry.Id);

            if (correctId == null)
            {
                Logging.Error("Can’t find correct ID");
                return;
            }

            if (!IsBookedForPlayer && BookingMode && !ReferenceEquals(o, ActualJoin) && !ReferenceEquals(o, ForceJoin))
            {
                if (_factory == null)
                {
                    Logging.Error("Booking: UI factory is missing");
                    return;
                }

                PrepareBookingUi();
                ProcessBookingResponse(await Task.Run(() => KunosApiProvider.TryToBook(Ip, PortHttp, Password, correctId, carEntry.AvailableSkin?.Id,
                                                                                       DriverName.GetOnline(), "")));
                return;
            }

            DisposeHelper.Dispose(ref _ui);
            IsBooked            = false;
            BookingErrorMessage = null;

            var properties = new Game.StartProperties(new Game.BasicProperties {
                CarId                = carEntry.Id,
                CarSkinId            = carEntry.AvailableSkin?.Id,
                TrackId              = Track?.Id,
                TrackConfigurationId = Track?.LayoutId
            }, null, null, null, new Game.OnlineProperties {
                RequestedCar   = correctId,
                ServerIp       = Ip,
                ServerName     = DisplayName,
                ServerPort     = PortRace,
                ServerHttpPort = PortHttp,
                Guid           = SteamIdHelper.Instance.Value,
                Password       = Password
            });

            var now = DateTime.Now;
            await GameWrapper.StartAsync(properties);

            var whatsGoingOn = properties.GetAdditional <WhatsGoingOn>();

            WrongPassword = whatsGoingOn?.Type == WhatsGoingOnType.OnlineWrongPassword;

            if (whatsGoingOn == null)
            {
                LastConnected = now;
                FileBasedOnlineSources.AddRecent(this).Forget();
                UpdateStats();
            }
        }
예제 #34
0
        private static BaseFinishedData GetFinishedData(Game.StartProperties properties, Game.Result result)
        {
            var conditions = properties?.GetAdditional <PlaceConditions>();
            var takenPlace = conditions?.GetTakenPlace(result) ?? PlaceConditions.UnremarkablePlace;

            Logging.Debug($"Place conditions: {conditions?.GetDescription()}, result: {result.GetDescription()}");

            if (result.GetExtraByType <Game.ResultExtraDrift>(out var drift))
            {
                return(new DriftFinishedData {
                    Points = drift.Points,
                    MaxCombo = drift.MaxCombo,
                    MaxLevel = drift.MaxLevel,
                    TakenPlace = takenPlace
                });
            }

            if (result.GetExtraByType <Game.ResultExtraTimeAttack>(out var timeAttack))
            {
                var bestLapTime = result.Sessions?.SelectMany(x => from lap in x.BestLaps where lap.CarNumber == 0 select lap.Time).MinOrDefault();
                return(new TimeAttackFinishedData {
                    Points = timeAttack.Points,
                    Laps = result.Sessions?.Sum(x => x.LapsTotalPerCar?.FirstOrDefault() ?? 0) ?? 0,
                    BestLapTime = bestLapTime == TimeSpan.Zero ? null : bestLapTime,
                    TakenPlace = takenPlace
                });
            }

            if (result.GetExtraByType <Game.ResultExtraBestLap>(out var bestLap) && bestLap.IsNotCancelled && result.Sessions?.Length == 1 &&
                result.Players?.Length == 1)
            {
                var bestLapTime = result.Sessions.SelectMany(x => from lap in x.BestLaps where lap.CarNumber == 0 select lap.Time).MinOrDefault();

                var sectorsPerSections  = result.Sessions.SelectMany(x => from lap in x.Laps where lap.CarNumber == 0 select lap.SectorsTime).ToList();
                var theoreticallLapTime = sectorsPerSections.FirstOrDefault()?.Select((x, i) => sectorsPerSections.Select(y => y[i]).Min()).Sum();

                return(result.Sessions[0].Name == AppStrings.Rsr_SessionName ? new RsrFinishedData {
                    Laps = result.Sessions.Sum(x => x.LapsTotalPerCar?.FirstOrDefault() ?? 0),
                    BestLapTime = bestLapTime == TimeSpan.Zero ? (TimeSpan?)null : bestLapTime,
                    TheoreticallLapTime = theoreticallLapTime,
                    TakenPlace = takenPlace
                } : new HotlapFinishedData {
                    Laps = result.Sessions.Sum(x => x.LapsTotalPerCar?.FirstOrDefault() ?? 0),
                    BestLapTime = bestLapTime == TimeSpan.Zero ? (TimeSpan?)null : bestLapTime,
                    TheoreticallLapTime = theoreticallLapTime,
                    TakenPlace = takenPlace
                });
            }

            var isOnline   = properties?.ModeProperties is Game.OnlineProperties;
            var playerName = isOnline && SettingsHolder.Drive.DifferentPlayerNameOnline
                    ? SettingsHolder.Drive.PlayerNameOnline : SettingsHolder.Drive.PlayerName;

            if (result.Sessions?.Length == 1 && result.Sessions[0].Name == Game.TrackDaySessionName && result.Players?.Length > 1)
            {
                var session    = result.Sessions[0];
                var playerLaps = session.LapsTotalPerCar?[0] ?? 1;
                session.LapsTotalPerCar = session.LapsTotalPerCar?.Select(x => Math.Min(x, playerLaps)).ToArray();
                session.Laps            = session.Laps?.Where(x => x.LapId < playerLaps).ToArray();
                session.BestLaps        = session.BestLaps?.Select(x => {
                    if (x.LapId < playerLaps)
                    {
                        return(x);
                    }
                    var best = session.Laps?.Where(y => y.CarNumber == x.CarNumber).MinEntryOrDefault(y => y.Time);
                    if (best == null)
                    {
                        return(null);
                    }
                    return(new Game.ResultBestLap {
                        Time = best.Time,
                        LapId = best.LapId,
                        CarNumber = x.CarNumber
                    });
                }).NonNull().ToArray();
            }

            var dragExtra    = result.GetExtraByType <Game.ResultExtraDrag>();
            var sessionsData = result.Sessions?.Select(session => {
                int[] takenPlaces;
                SessionFinishedData data;

                if (dragExtra != null)
                {
                    data = new DragFinishedData {
                        BestReactionTime = dragExtra.ReactionTime,
                        Total            = dragExtra.Total,
                        Wins             = dragExtra.Wins,
                        Runs             = dragExtra.Runs,
                    };

                    var delta   = dragExtra.Wins * 2 - dragExtra.Runs;
                    takenPlaces = new[] {
                        delta >= 0 ? 0 : 1,
                        delta <= 0 ? 0 : 1
                    };
                }
                else
                {
                    data        = new SessionFinishedData(session.Name?.ApartFromLast(@" Session"));
                    takenPlaces = session.GetTakenPlacesPerCar();
                }

                var sessionBestLap = session.BestLaps?.MinEntryOrDefault(x => x.Time);
                var sessionBest    = sessionBestLap?.Time;

                data.PlayerEntries = (
                    from player in result.Players
                    let car = CarsManager.Instance.GetById(player.CarId ?? "")
                              let carSkin = car?.GetSkinById(player.CarSkinId ?? "")
                                            select new { Player = player, Car = car, CarSkin = carSkin }
                    ).Select((entry, i) => {
                    var bestLapTime = session.BestLaps?.Where(x => x.CarNumber == i).MinEntryOrDefault(x => x.Time)?.Time;
                    var laps        = session.Laps?.Where(x => x.CarNumber == i).Select(x => new SessionFinishedData.PlayerLapEntry {
                        LapNumber          = x.LapId + 1,
                        Sectors            = x.SectorsTime,
                        Cuts               = x.Cuts,
                        TyresShortName     = x.TyresShortName,
                        Total              = x.Time,
                        DeltaToBest        = bestLapTime.HasValue ? x.Time - bestLapTime.Value : (TimeSpan?)null,
                        DeltaToSessionBest = sessionBest.HasValue ? x.Time - sessionBest.Value : (TimeSpan?)null,
                    }).ToArray();

                    var lapTimes = laps?.Skip(1).Select(x => x.Total.TotalSeconds).Where(x => x > 10d).ToList();
                    double?progress, spread;
                    if (lapTimes == null || lapTimes.Count < 2)
                    {
                        progress = null;
                        spread   = null;
                    }
                    else
                    {
                        var firstHalf    = lapTimes.Count / 2;
                        var firstMedian  = lapTimes.Take(firstHalf).Median();
                        var secondMedian = lapTimes.Skip(firstHalf).Median();
                        progress         = 1d - secondMedian / firstMedian;
                        spread           = (lapTimes.Max() - lapTimes.Min()) / bestLapTime?.TotalSeconds;
                    }

                    return(new SessionFinishedData.PlayerEntry {
                        Name = i == 0 ? playerName : entry.Player.Name,
                        IsPlayer = i == 0,
                        Index = i,
                        Car = entry.Car,
                        CarSkin = entry.CarSkin,
                        TakenPlace = i < takenPlaces?.Length ? takenPlaces[i] + 1 : DefinitelyNonPrizePlace,
                        PrizePlace = takenPlaces?.Length > 1,
                        LapsCount = session.LapsTotalPerCar?.ArrayElementAtOrDefault(i) ?? 0,
                        BestLapTime = bestLapTime,
                        DeltaToSessionBest = sessionBestLap?.CarNumber == i ? null : bestLapTime - sessionBest,
                        TotalTime = session.Laps?.Where(x => x.CarNumber == i).Select(x => x.SectorsTime.Sum()).Sum(),
                        Laps = laps,
                        LapTimeProgress = progress,
                        LapTimeSpread = spread
                    });
                }).OrderBy(x => x.TakenPlace).ToList();

                if (data.PlayerEntries.Count > 0)
                {
                    var maxLaps       = data.PlayerEntries.Select(x => x.Laps.Length).Max();
                    var bestTotalTime = data.PlayerEntries.Where(x => x.Laps.Length == maxLaps).MinEntryOrDefault(x => x.TotalTime ?? TimeSpan.MaxValue);
                    foreach (var entry in data.PlayerEntries)
                    {
                        var lapsDelta = maxLaps - entry.Laps.Length;
                        if (bestTotalTime == entry)
                        {
                            entry.TotalTimeDelta = "-";
                        }
                        else if (lapsDelta > 0)
                        {
                            entry.TotalTimeDelta = $"+{lapsDelta} {PluralizingConverter.Pluralize(lapsDelta, "lap")}";
                        }
                        else
                        {
                            var t = entry.TotalTime - bestTotalTime?.TotalTime;
                            var v = t?.ToMillisecondsString();
                            entry.TotalTimeDelta = t == TimeSpan.Zero ? "" : v != null ? $"+{v}" : null;
                        }
                    }
                }

                var bestProgress = (from player in data.PlayerEntries
                                    where player.LapTimeProgress > 0.03
                                    orderby player.LapTimeProgress descending
                                    select player).FirstOrDefault();
                var bestConsistent = (from player in data.PlayerEntries
                                      where player.LapTimeSpread < 0.02
                                      orderby player.LapTimeSpread descending
                                      select player).FirstOrDefault();

                data.RemarkableNotes = new[] {
                    sessionBestLap == null ? null :
                    new SessionFinishedData.RemarkableNote("[b]Best lap[/b] made by ", data.PlayerEntries.GetByIdOrDefault(sessionBestLap.CarNumber),
                                                           null),
                    new SessionFinishedData.RemarkableNote("[b]The Best Off-roader Award[/b] goes to ", (from player in data.PlayerEntries
                                                                                                         let cuts =
                                                                                                             (double)player.Laps.Sum(x => x.Cuts)
                                                                                                             / player.Laps.Length
                                                                                                             where cuts > 1.5
                                                                                                             orderby cuts descending
                                                                                                             select player).FirstOrDefault(), null),
                    new SessionFinishedData.RemarkableNote("[b]Remarkable progress[/b] shown by ", bestProgress, null),
                    new SessionFinishedData.RemarkableNote("[b]The most consistent[/b] is ", bestConsistent, null),
                }.Where(x => x?.Player != null).ToList();
                return(data);
            }).ToList();

            return(sessionsData?.Count == 1 ? (BaseFinishedData)sessionsData.First() :
                   sessionsData?.Any() == true ? new SessionsFinishedData(sessionsData) : null);
        }
예제 #35
0
        private static async Task <Game.Result> StartAsync_Ui(Game.StartProperties properties, GameMode mode)
        {
            using (var ui = _uiFactory.Create()) {
                Logging.Write($"Starting game: {properties.GetDescription()}");
                ui.Show(properties, mode);

                CancellationTokenSource linked = null;
                IsInGame = true;

                try {
                    FileUtils.TryToDelete(AcPaths.GetLogFilename());

                    Game.Result result;
                    using (ReplaysExtensionSetter.OnlyNewIfEnabled())
                        using (ScreenshotsConverter.OnlyNewIfEnabled()) {
                            Started?.Invoke(null, new GameStartedArgs(properties, mode));

                            if (mode == GameMode.Race)
                            {
                                properties.SetAdditional(new RaceCommandExecutor(properties));
                                properties.SetAdditional(new DBoxIntegration());
                                if (SettingsHolder.Drive.ContinueOnEscape)
                                {
                                    properties.SetAdditional(new ContinueRaceHelper());
                                }
                            }
                            else if (mode == GameMode.Replay)
                            {
                                properties.SetAdditional(new ReplayCommandExecutor(properties));
                            }

                            var cancellationToken = ui.CancellationToken;
                            if (SettingsHolder.Drive.ImmediateCancel)
                            {
                                var cancelHelper = new ImmediateCancelHelper();
                                linked            = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, cancelHelper.GetCancellationToken());
                                cancellationToken = linked.Token;
                                properties.SetAdditional(cancelHelper);
                                properties.SetKeyboardListener = true;
                            }

                            if (mode == GameMode.Replay)
                            {
                                await PrepareReplay(properties, ui, cancellationToken);
                            }

                            if (SettingsHolder.Drive.LoadPatchDataAutomatically && PatchHelper.IsActive())
                            {
                                var trackId = string.IsNullOrWhiteSpace(properties.BasicProperties?.TrackConfigurationId)
                                    ? properties.BasicProperties?.TrackId
                                    : properties.BasicProperties?.TrackId + @"/" + properties.BasicProperties?.TrackConfigurationId;
                                using (var cancellation = new CancellationTokenSource()) {
                                    ui.OnProgress("Loading data for Custom Shaders Patch…", AsyncProgressEntry.Indetermitate, () => { cancellation.Cancel(); });
                                    var carName   = properties.BasicProperties?.CarId == null ? null : CarsManager.Instance.GetById(properties.BasicProperties?.CarId);
                                    var trackName = trackId == null ? null : TracksManager.Instance.GetById(trackId)?.Name ?? trackId;
                                    await PatchTracksDataUpdater.Instance.TriggerAutoLoadAsync(trackId,
                                                                                               PatchSubProgress($"Config for track {trackName}"), cancellation.Token);

                                    await PatchTracksVaoDataUpdater.Instance.TriggerAutoLoadAsync(trackId,
                                                                                                  PatchSubProgress($"Ambient occlusion patch for track {trackName}"), cancellation.Token);

                                    await PatchBackgroundDataUpdater.Instance.TriggerAutoLoadAsync(trackId,
                                                                                                   PatchSubProgress($"Backgrounds for track {trackName}"), cancellation.Token);

                                    await PatchCarsDataUpdater.Instance.TriggerAutoLoadAsync(properties.BasicProperties?.CarId,
                                                                                             PatchSubProgress($"Config for car {carName}"), cancellation.Token);

                                    await PatchCarsVaoDataUpdater.Instance.TriggerAutoLoadAsync(properties.BasicProperties?.CarId,
                                                                                                PatchSubProgress($"Ambient occlusion patch for car {carName}"), cancellation.Token);

                                    ui.OnProgress("Final preparations…");

                                    IProgress <AsyncProgressEntry> PatchSubProgress(string target)
                                    {
                                        return(new Progress <AsyncProgressEntry>(p => ui.OnProgress("Loading data for Custom Shaders Patch…",
                                                                                                    new AsyncProgressEntry($"{target}\n{p.Message ?? @"…"}", p.IsReady || p.Progress == null ? 0d : p.Progress),
                                                                                                    () => cancellation.Cancel())));
                                    }
                                }
                            }

                            result = await Game.StartAsync(CreateStarter(properties), properties, new ProgressHandler(ui), cancellationToken);
                        }

                    Logging.Write($"Result: {result?.GetDescription() ?? @"<NULL>"}");
                    if (ui.CancellationToken.IsCancellationRequested)
                    {
                        ui.OnError(new UserCancelledException());
                        return(null);
                    }

                    var whatsGoingOn = mode != GameMode.Race || result == null?AcLogHelper.TryToDetermineWhatsGoingOn() : null;

                    if (whatsGoingOn != null)
                    {
                        properties.SetAdditional(whatsGoingOn);
                    }

                    if (mode == GameMode.Race)
                    {
                        var param = new GameEndedArgs(properties, result);
                        Ended?.Invoke(null, param);
                        /* TODO: should set result to null if param.Cancel is true? */

                        var replayHelper = new ReplayHelper(properties, result);
                        (result == null || param.Cancel ? Cancelled : Finished)?.Invoke(null, new GameFinishedArgs(properties, result));

                        ui.OnResult(result, replayHelper);
                    }
                    else
                    {
                        ui.OnResult(null, null);
                    }

                    return(result);
                } catch (Exception e) when(e.IsCancelled())
                {
                    // ui.OnError(new UserCancelledException());
                    ui.OnResult(null, null);
                    return(null);
                } catch (Exception e) {
                    Logging.Warning(e);
                    ui.OnError(e);
                    return(null);
                } finally {
                    linked?.Dispose();
                    IsInGame = false;
                }
            }
        }
예제 #36
0
        void IGameUi.Show(Game.StartProperties properties) {
            _properties = properties;

            ShowDialogWithoutBlocking();
            Model.WaitingStatus = AppStrings.Race_Initializing;
        }