Exemplo n.º 1
0
        protected void LoadCountry(JObject json)
        {
            var value = json.GetStringValueOnly("country")?.Trim();

            Country = value != null?AcStringValues.CountryFromTag(value) ?? value:
                      Tags.Select(AcStringValues.CountryFromTag).FirstOrDefault(x => x != null);
        }
Exemplo n.º 2
0
        private static string GetItemName(string key, out string category)
        {
            string name;

            var pieces = key.Split(new[] { '@' }, 2);

            if (pieces.Length == 2)
            {
                category = AcStringValues.NameFromId(pieces[0].ToLower());
                name     = pieces[1];
            }
            else
            {
                category = null;
                name     = key;
            }

            name = AcStringValues.NameFromId(name.ToLowerInvariant(), false);
            name = Regex.Replace(name, @"\bk\b", "coefficient");
            name = Regex.Replace(name, @"\bmult\b", "multiplier");
            name = Regex.Replace(name, @"\bref\b", "reference");
            name = Regex.Replace(name, @"\bd\b", "Δ");
            name = Regex.Replace(name, @"\b(?:Cx|Fz|Ls|rr|Xmu)\b", m => m.Value.ToUpperInvariant());
            name = Regex.Replace(name, @"\b(?<= )\d\b", m => $"#{m.Value}");
            name = Regex.Replace(name, @"\b[dD](x|y|camber)\b", m => $"Δ{m.Groups[1].Value.ToTitle()}");
            name = Regex.Replace(name, @"\bexp([xy])\b", m => $"exp({m.Groups[1].Value.ToUpperInvariant()})");
            return(name);
        }
Exemplo n.º 3
0
        protected override void LoadData(JObject json)
        {
            base.LoadData(json);

            Brand = json.GetStringValueOnly("brand");
            if (string.IsNullOrEmpty(Brand))
            {
                AddError(AcErrorType.Data_CarBrandIsMissing);
            }

            if (Country == null && Brand != null)
            {
                Country = AcStringValues.CountryFromBrand(Brand);
            }

            CarClass = json.GetStringValueOnly("class");
            ParentId = json.GetStringValueOnly("parent");

            var specsObj = json["specs"] as JObject;

            SpecsBhp          = specsObj?.GetStringValueOnly("bhp");
            SpecsTorque       = specsObj?.GetStringValueOnly("torque");
            SpecsWeight       = specsObj?.GetStringValueOnly("weight");
            SpecsTopSpeed     = specsObj?.GetStringValueOnly("topspeed");
            SpecsAcceleration = specsObj?.GetStringValueOnly("acceleration");
            SpecsPwRatio      = specsObj?.GetStringValueOnly("pwratio");

            SpecsTorqueCurve = new GraphData(json["torqueCurve"] as JArray);
            SpecsPowerCurve  = new GraphData(json["powerCurve"] as JArray);
        }
Exemplo n.º 4
0
        public static IEnumerable <string> CleanUp(IEnumerable <string> tags)
        {
            return(tags.Select(x => {
                var s = x.Trim().ApartFromLast("\"]").ApartFromFirst("[\"").Trim();

                if (Regex.IsMatch(s, @"^#?[abAB]\d\d?$"))
                {
                    return null;
                }

                if (s[0] == '#')
                {
                    return s;
                }

                var t = s.ToLower();
                switch (t)
                {
                case "natural":
                    return null;

                case "racing":
                    return @"race";

                case "american":
                    return @"usa";

                case "road":
                    return @"street";

                default:
                    return AcStringValues.CountryFromTag(t)?.ToLower() ?? t;
                }
            }).Where(x => !string.IsNullOrWhiteSpace(x)).Distinct());
        }
Exemplo n.º 5
0
        protected override void LoadData(JObject json)
        {
            base.LoadData(json);

            if (Version == null && Description != null)
            {
                string description;
                Version = AcStringValues.GetVersionFromName(Description, out description);
                if (Version != null)
                {
                    Description = description;
                }
            }

            City    = json.GetStringValueOnly("city");
            GeoTags = json.GetGeoTagsValueOnly("geotags");

            if (Country == null)
            {
                foreach (var country in Tags.Select(AcStringValues.CountryFromTag).Where(x => x != null))
                {
                    Country = country;
                    break;
                }
            }

            SpecsLength   = json.GetStringValueOnly("length");
            SpecsWidth    = json.GetStringValueOnly("width");
            SpecsPitboxes = json.GetStringValueOnly("pitboxes");
        }
Exemplo n.º 6
0
        private WorkshopValidatedItem TestCarBrand()
        {
            var originalBrand = Target.Brand;

            if (string.IsNullOrWhiteSpace(originalBrand))
            {
                var brandFromName = AcStringValues.BrandFromName(Target.NameEditable ?? "");
                if (brandFromName != null)
                {
                    return(new WorkshopValidatedItem($"Car brand will be “{brandFromName}”",
                                                     () => Target.Brand = brandFromName, () => Target.Brand = originalBrand));
                }
                return(new WorkshopValidatedItem("Car brand is required", WorkshopValidatedState.Failed));
            }

            var trimmed    = originalBrand.Trim();
            var knownBrand = FilesStorage.Instance.GetContentFiles(ContentCategory.BrandBadges).Select(x => x.Name).FirstOrDefault(x =>
                                                                                                                                   string.Equals(x, trimmed, StringComparison.OrdinalIgnoreCase));

            if (knownBrand != null)
            {
                return(knownBrand == originalBrand
                        ? new WorkshopValidatedItem("Car brand is correct")
                        : new WorkshopValidatedItem($"Car brand might contain a typo, will be changed to {knownBrand}",
                                                    () => Target.Brand = knownBrand, () => Target.Brand = originalBrand));
            }

            return(new WorkshopValidatedItem("Car brand is unknown, car won’t be in any known car brand category", WorkshopValidatedState.Warning));
        }
Exemplo n.º 7
0
        protected override void LoadData(IniFile ini)
        {
            Name        = ini["SERIES"].GetPossiblyEmpty("NAME");
            Code        = ini["SERIES"].GetPossiblyEmpty("CODE");
            Description = AcStringValues.DecodeDescription(ini["SERIES"].GetPossiblyEmpty("DESCRIPTION"));

            PointsForPlace          = ini["SERIES"].GetPossiblyEmpty("POINTS")?.Split(',').Select(x => FlexibleParser.TryParseInt(x)).OfType <int>().ToArray();
            ChampionshipPointsGoal  = ini["GOALS"].GetIntNullable("POINTS") ?? 0;
            ChampionshipRankingGoal = ini["GOALS"].GetIntNullable("RANKING") ?? 0;
            ThirdPlacesGoal         = ini["GOALS"].GetIntNullable("TIER1") ?? 0;
            SecondPlacesGoal        = ini["GOALS"].GetIntNullable("TIER2") ?? 0;
            FirstPlacesGoal         = ini["GOALS"].GetIntNullable("TIER3") ?? 0;
            Type = ChampionshipPointsGoal == 0 && ChampionshipRankingGoal == 0 || PointsForPlace?.Sum() == 0
                    ? KunosCareerObjectType.SingleEvents : KunosCareerObjectType.Championship;

            RequiredSeries    = ini["SERIES"].GetStrings("REQUIRES").ToArray();
            RequiredAnySeries = ini["SERIES"].GetBool("REQUIRESANY", false);

            ChampionshipPointsPerPlace = ini["SERIES"].GetStrings("POINTS").Select(x => FlexibleParser.TryParseInt(x)).OfType <int>().ToArray();

            if (Type == KunosCareerObjectType.Championship)
            {
                LoadOpponents();
            }
        }
Exemplo n.º 8
0
 protected virtual void LoadYear(JObject json)
 {
     Year = json.GetIntValueOnly("year");
     if (!Year.HasValue && Name != null)
     {
         Year = AcStringValues.GetYearFromName(Name) ?? AcStringValues.GetYearFromId(Name);
     }
 }
Exemplo n.º 9
0
        protected override bool LoadJsonOrThrow()
        {
            if (!File.Exists(JsonFilename))
            {
                ClearData();
                Name    = AcStringValues.NameFromId(Id);
                Changed = true;
                return(true);
            }

            return(base.LoadJsonOrThrow());
        }
Exemplo n.º 10
0
        private static int GetCategory(string s)
        {
            if (s[0] == '#')
            {
                return(0);
            }

            switch (s.ToLower())
            {
            case "4wd":
            case "awd":
            case "fwd":
            case "rwd":
                return(10);

            case "automatic":
            case "manual":
            case "semiautomatic":
            case "sequential":
                return(20);

            case "h-shifter":
                return(21);

            case "compressor":
            case "turbo":
            case "v4":
            case "v6":
            case "v8":
            case "v10":
            case "v12":
                return(25);

            case "lightweight":
            case "heavyweight":
            case "subcompact":
                return(28);

            case "drift":
            case "rally":
            case "race":
            case "racing":
            case "street":
            case "sportscar":
            case "trackday":
            case "wrc":
                return(30);

            default:
                return(AcStringValues.CountryFromTag(s) != null ? 100 : 50);
            }
        }
Exemplo n.º 11
0
 public CarSkinObject([NotNull] string carId, IFileAcManager manager, string id, bool enabled)
     : base(manager, id, enabled)
 {
     CarId       = carId;
     _nameFromId = new Lazy <string>(() => {
         var cut = Regex.Replace(Id, @"^\d\d?_", "");
         if (string.IsNullOrEmpty(cut))
         {
             cut = Id;
         }
         return(AcStringValues.NameFromId(cut));
     });
 }
Exemplo n.º 12
0
        protected override IEnumerable <string> GetForcedTags()
        {
            var drivetrainIni = Target.AcdData?.GetIniFile("drivetrain.ini");
            var tractionType  = drivetrainIni?["TRACTION"].GetNonEmpty("TYPE");

            if (tractionType == "RWD")
            {
                yield return("rwd");
            }
            else if (tractionType == "FWD")
            {
                yield return("fwd");
            }
            else if (tractionType == "AWD")
            {
                yield return("awd");
            }

            var gearsCount      = drivetrainIni?["GEARS"].GetIntNullable("COUNT");
            var supportsShifter = drivetrainIni?["GEARBOX"].GetBoolNullable("SUPPORTS_SHIFTER");

            if (gearsCount > 1 && supportsShifter.HasValue)
            {
                yield return(supportsShifter.Value ? "manual" : "semiautomatic");
            }

            if (Target.CarClass == "street")
            {
                yield return("street");
            }
            else if (Target.CarClass == "race")
            {
                yield return("race");
            }
            else
            {
                yield return(GuessCarClass());
            }

            yield return(Target.Country != null?AcStringValues.CountryFromTag(Target.Country) : GuessCountry());

            if (Target.AcdData?.GetIniFile("engine.ini")["TURBO_0"].ContainsKey("MAX_BOOST") == true)
            {
                yield return("turbo");
            }

            if (Target.Year < 1990)
            {
                yield return("vintage");
            }
        }
Exemplo n.º 13
0
 public override void SaveData(IniFile ini)
 {
     ini["SERIES"].Set("NAME", Name);
     ini["SERIES"].Set("CODE", Code);
     ini["SERIES"].Set("DESCRIPTION", AcStringValues.EncodeDescription(Description));
     ini["SERIES"].Set("POINTS", PointsForPlace.JoinToString(@","));
     ini["GOALS"].Set("POINTS", ChampionshipPointsGoal);
     ini["GOALS"].Set("RANKING", ChampionshipRankingGoal);
     ini["GOALS"].Set("TIER1", ThirdPlacesGoal);
     ini["GOALS"].Set("TIER2", SecondPlacesGoal);
     ini["GOALS"].Set("TIER3", FirstPlacesGoal);
     ini["SERIES"].Set("REQUIRES", RequiredSeries);
     ini["SERIES"].Set("REQUIRESANY", RequiredAnySeries);
 }
Exemplo n.º 14
0
        protected void LoadVersionInfo(JObject json)
        {
            Author  = json.GetStringValueOnly("author")?.Trim() ?? (TestIfKunos() ? AuthorKunos : null);
            Version = json.GetStringValueOnly("version")?.Trim();
            Url     = json.GetStringValueOnly("url")?.Trim();

            if (Version == null && Name != null)
            {
                string name;
                Version = AcStringValues.GetVersionFromName(Name, out name);
                if (Version != null)
                {
                    Name = name;
                }
            }
        }
Exemplo n.º 15
0
        protected override void LoadYear(JObject json)
        {
            Year = json.GetIntValueOnly("year");
            if (Year.HasValue)
            {
                return;
            }

            int year;

            if (DataProvider.Instance.CarYears.TryGetValue(Id, out year))
            {
                Year = year;
            }
            else if (Name != null)
            {
                Year = AcStringValues.GetYearFromName(Name) ?? AcStringValues.GetYearFromId(Name);
            }
        }
Exemplo n.º 16
0
        protected override void LoadData(IniFile ini)
        {
            Name        = ini["EVENT"].GetPossiblyEmpty("NAME");
            Description = AcStringValues.DecodeDescription(ini["EVENT"].GetPossiblyEmpty("DESCRIPTION"));

            TrackId = ini["RACE"].GetNonEmpty("TRACK");
            TrackConfigurationId = ini["RACE"].GetNonEmpty("CONFIG_TRACK");
            CarId     = ini["RACE"].GetNonEmpty("MODEL");
            CarSkinId = ini["CAR_0"].GetNonEmpty("SKIN");
            WeatherId = ini["WEATHER"].GetNonEmpty("NAME") ?? WeatherManager.Instance.GetDefault()?.Id;

            Time            = (int)Game.ConditionProperties.GetSeconds(ini["LIGHTING"].GetInt("SUN_ANGLE", 40));
            Temperature     = ini["TEMPERATURE"].GetDouble("AMBIENT", 26);
            RoadTemperature = ini["TEMPERATURE"].GetDouble("ROAD", 32);

            TrackPreset = Game.DefaultTrackPropertiesPresets.GetByIdOrDefault(ini["DYNAMIC_TRACK"].GetIntNullable("PRESET")) ??
                          Game.DefaultTrackPropertiesPresets[4];
            DisplayType = ini.ContainsKey(@"SESSION_1") ? ToolsStrings.Common_Weekend :
                          (ini["SESSION_0"].GetNonEmpty("NAME")?.Replace(@" Session", "") ?? ToolsStrings.Session_Race);

            StartingPosition = ini["SESSION_0"].GetIntNullable("STARTING_POSITION");
            OpponentsCount   = ini["RACE"].GetInt("CARS", 1) - 1;

            if (OpponentsCount > 0 && StartingPosition == null)
            {
                StartingPosition = OpponentsCount + 1;
            }

            if (StartingPosition != null || ini.ContainsKey(@"SESSION_1"))
            {
                Laps = ini["SESSION_0"].GetIntNullable("LAPS") ?? ini["RACE"].GetIntNullable("RACE_LAPS") ?? 0;
            }
            else
            {
                Laps = null;
            }

            AiLevel = ini["RACE"].GetInt("AI_LEVEL", 100);

            LoadObjects();
            LoadConditions(ini);
            LoadProgress();
        }
Exemplo n.º 17
0
        public static MultiSolution TryToCreateNewFile(AcJsonObjectNew target)
        {
            if (target is ShowroomObject)
            {
                return(new MultiSolution(
                           ToolsStrings.Solving_CreateNewFile,
                           ToolsStrings.Solving_CreateNewFile_Commentary,
                           e => {
                    var jObject = new JObject {
                        [@"name"] = AcStringValues.NameFromId(e.Target.Id)
                    };

                    FileUtils.EnsureFileDirectoryExists(((AcJsonObjectNew)e.Target).JsonFilename);
                    File.WriteAllText(((AcJsonObjectNew)e.Target).JsonFilename, jObject.ToString());
                }));
            }

            if (target is CarSkinObject)
            {
                return(new MultiSolution(
                           ToolsStrings.Solving_CreateNewFile,
                           ToolsStrings.Solving_CreateNewFile_Commentary,
                           e => {
                    var jObject = new JObject {
                        [@"skinname"] = CarSkinObject.NameFromId(e.Target.Id),
                        [@"drivername"] = "",
                        [@"country"] = "",
                        [@"team"] = "",
                        [@"number"] = @"0"
                    };

                    if (!SettingsHolder.Content.SkinsSkipPriority)
                    {
                        jObject[@"priority"] = 1;
                    }

                    FileUtils.EnsureFileDirectoryExists(((AcJsonObjectNew)e.Target).JsonFilename);
                    File.WriteAllText(((AcJsonObjectNew)e.Target).JsonFilename, jObject.ToString());
                }));
            }

            return(null);
        }
Exemplo n.º 18
0
 protected override bool IsTagAllowed(string tag)
 {
     if (tag.StartsWith("#"))
     {
         return(tag.Length > 3 || tag.Length > 1 && tag[1] != 'A');
     }
     if (tag == "vintage" && Target.Year > 2005)
     {
         return(false);
     }
     if (_prohibitedTags.Contains(tag))
     {
         return(false);
     }
     if (AcStringValues.CountryFromTag(tag) != null)
     {
         return(false);
     }
     return(base.IsTagAllowed(tag));
 }
Exemplo n.º 19
0
        public IAcObjectNew AddNew(string id = null)
        {
            var mainDirectory = Directories.GetMainDirectory();

            if (id == null)
            {
                var uniqueId = Path.GetFileName(FileUtils.EnsureUnique(Path.Combine(mainDirectory, "skin")));
                id = Prompt.Show("Choose a name for a new car skin:", "New car skin", required: true, maxLength: 80, placeholder: "?",
                                 defaultValue: uniqueId);
                if (id == null)
                {
                    return(null);
                }
            }

            var directory = Directories.GetLocation(id, true);

            if (Directory.Exists(directory))
            {
                throw new InformativeException("Can’t add a new object", $"ID “{id}” is already taken.");
            }

            using (IgnoreChanges()) {
                Directory.CreateDirectory(directory);
                File.WriteAllText(Path.Combine(directory, "ui_skin.json"), new JObject {
                    ["skinname"]   = AcStringValues.NameFromId(id),
                    ["drivername"] = "",
                    ["country"]    = "",
                    ["team"]       = "",
                    ["number"]     = "",
                    ["priority"]   = 0
                }.ToString(Formatting.Indented));

                var obj = CreateAndLoadAcObject(id, true);
                InnerWrappersList.Add(new AcItemWrapper(this, obj));
                UpdateList(true);

                return(obj);
            }
        }
Exemplo n.º 20
0
        protected virtual WorkshopValidatedItem TestCountry()
        {
            var originalCountry = Target.Country;
            var country         = originalCountry != null?AcStringValues.CountryFromTag(originalCountry) : GuessCountry();

            if (country != null)
            {
                return(country != originalCountry
                        ? new WorkshopValidatedItem($"There might be a typo in the country’s name, will be changed to “{country}”",
                                                    () => Target.Country = country, () => Target.Country = originalCountry)
                        : new WorkshopValidatedItem("Country is correct"));
            }

            if (originalCountry != null)
            {
                return(new WorkshopValidatedItem("There might be a typo in the country’s name, it’s unknown to CM", WorkshopValidatedState.Failed));
            }

            return(CountryRequired
                    ? new WorkshopValidatedItem("Country is required", WorkshopValidatedState.Failed)
                    : new WorkshopValidatedItem("Country is not set, but it’s optional"));
        }
Exemplo n.º 21
0
        protected sealed override void AddNewIfMissing(IList <SelectTag> list, TObject obj)
        {
            var value = obj.Tags;

            for (var j = value.Count - 1; j >= 0; j--)
            {
                var tagValue = value[j];

                if (_ignored.Contains(tagValue))
                {
                    continue;
                }

                var isSpecial = tagValue.StartsWith(@"#");
                var tagName   = isSpecial ? tagValue.Substring(1).TrimStart() : tagValue;

                for (var i = list.Count - 1; i >= 0; i--)
                {
                    var item = list[i];
                    if (string.Equals(item.DisplayName, tagName, StringComparison.Ordinal))
                    {
                        IncreaseCounter(obj, item);
                        item.Accented |= isSpecial;
                        goto Next;
                    }
                }

                if (!isSpecial && (AcStringValues.CountryFromTag(tagValue) != null || IsIgnored(obj, tagValue)))
                {
                    _ignored.Add(tagValue);
                    continue;
                }

                AddNewIfMissing(list, obj, new SelectTag(tagName, tagValue));
                Next :;
            }
        }
Exemplo n.º 22
0
        public TagsCollection CleanUp()
        {
            // TODO: Special case for tracks?
            return(new TagsCollection(this.Select(x => {
                var s = x.Trim();

                if (Regex.IsMatch(s, @"^#?[abAB]\d\d?$"))
                {
                    return null;
                }

                if (s[0] == '#')
                {
                    return s;
                }

                var t = s.ToLower();
                switch (t)
                {
                case "natural":
                    return null;

                case "racing":
                    return @"race";

                case "american":
                    return @"usa";

                case "road":
                    return @"street";

                default:
                    return AcStringValues.CountryFromTag(t)?.ToLower() ?? t;
                }
            }).Where(x => !string.IsNullOrWhiteSpace(x)).Distinct()));
        }
Exemplo n.º 23
0
 public CmThemeEntry([NotNull] string path, [NotNull] string id, string version)
     : base(path, id, AcStringValues.NameFromId(id.ApartFromLast(".xaml", StringComparison.OrdinalIgnoreCase)), version)
 {
 }
Exemplo n.º 24
0
 private static string GetName(string id, string name)
 {
     return(name ?? AcStringValues.NameFromId(id));
 }
Exemplo n.º 25
0
 public SystemConfigEntry([NotNull] string path, [NotNull] string id, string name = null)
     : base(path, id, name ?? AcStringValues.NameFromId(id.ApartFromLast(".ini", StringComparison.OrdinalIgnoreCase)))
 {
     _destination = Path.Combine(AcPaths.GetSystemCfgDirectory(AcRootDirectory.Instance.RequireValue), id);
 }
Exemplo n.º 26
0
 public TexturesConfigEntry([NotNull] string path, [NotNull] string id, string name = null) : base(path, id, name ?? AcStringValues.NameFromId(id))
 {
     _destination = Path.Combine(AcRootDirectory.Instance.RequireValue, "content", "texture", id);
 }
Exemplo n.º 27
0
        protected override string GetBaseId()
        {
            var id = Path.GetFileNameWithoutExtension(_filename)?.ToLower();

            return(AcStringValues.IsAppropriateId(id) ? id : null);
        }
Exemplo n.º 28
0
 protected override string GuessCountry()
 {
     return(base.GuessCountry() ?? (Target.Brand != null ? AcStringValues.CountryFromBrand(Target.Brand) : null));
 }
Exemplo n.º 29
0
        private async Task <ContentEntryBase> CheckDirectoryNode(DirectoryNode directory, CancellationToken cancellation)
        {
            if (directory.Parent?.NameLowerCase == "python" && directory.Parent.Parent?.NameLowerCase == "apps" ||
                directory.HasSubFile(directory.Name + ".py"))
            {
                var id = directory.Name;
                if (id == null)
                {
                    // It’s unlikely there will be a car or a track in apps/python directory
                    return(null);
                }

                // App?
                var root = directory.Parent?.Parent?.Parent;
                var gui  = root?.GetSubDirectory("content")?.GetSubDirectory("gui")?.GetSubDirectory("icons");

                // Collecting values…
                var    missing = false;
                var    uiAppFound = false;
                string version = null, name = null;

                // Maybe, it’s done nicely?
                var uiApp = directory.GetSubDirectory("ui")?.GetSubFile("ui_app.json");
                if (uiApp != null)
                {
                    uiAppFound = true;
                    var data = await uiApp.Info.ReadAsync();

                    if (data == null)
                    {
                        missing = true;
                    }
                    else
                    {
                        var parsed = JsonExtension.Parse(data.ToUtf8String());
                        name    = parsed.GetStringValueOnly("name");
                        version = parsed.GetStringValueOnly("version");
                    }
                }

                // Let’s try to guess version
                if (version == null && !uiAppFound)
                {
                    foreach (var c in PythonAppObject.VersionSources.Select(directory.GetSubFile).NonNull())
                    {
                        var r = await c.Info.ReadAsync();

                        if (r == null)
                        {
                            missing = true;
                        }
                        else
                        {
                            version = PythonAppObject.GetVersion(r.ToUtf8String());
                            if (version != null)
                            {
                                break;
                            }
                        }
                    }
                }

                // And icon
                byte[]          icon;
                List <FileNode> icons;

                if (gui != null)
                {
                    icons = gui.Files.Where(x => x.NameLowerCase.EndsWith("_on.png") || x.NameLowerCase.EndsWith("_off.png")).ToList();
                    var mainIcon = icons.GetByIdOrDefault(directory.NameLowerCase + "_off.png") ??
                                   icons.OrderByDescending(x => x.NameLowerCase.Length).FirstOrDefault();

                    icon = await(mainIcon?.Info.ReadAsync() ?? Task.FromResult((byte[])null));
                    if (mainIcon != null && icon == null)
                    {
                        missing = true;
                    }

                    cancellation.ThrowIfCancellationRequested();
                }
                else
                {
                    icon  = null;
                    icons = null;
                }

                if (missing)
                {
                    throw new MissingContentException();
                }

                return(new PythonAppContentEntry(directory.Key ?? "", id,
                                                 name ?? id, version, icon, icons?.Select(x => x.Key)));
            }

            var ui = directory.GetSubDirectory("ui");

            if (ui != null)
            {
                // Is it a car?
                var uiCar = ui.GetSubFile("ui_car.json");
                if (uiCar != null)
                {
                    var icon = await(ui.GetSubFile("badge.png")?.Info.ReadAsync() ?? Task.FromResult((byte[])null));
                    cancellation.ThrowIfCancellationRequested();

                    var data = await uiCar.Info.ReadAsync() ?? throw new MissingContentException();

                    var parsed = JsonExtension.Parse(data.ToUtf8String());
                    var carId  = directory.Name ??
                                 directory.GetSubDirectory("sfx")?.Files.Select(x => x.NameLowerCase)
                                 .FirstOrDefault(x => x.EndsWith(@".bank") && x.Count('.') == 1 && x != @"common.bank")?.ApartFromLast(@".bank");

                    if (carId != null)
                    {
                        return(new CarContentEntry(directory.Key ?? "", carId, parsed.GetStringValueOnly("parent") != null,
                                                   parsed.GetStringValueOnly("name"), parsed.GetStringValueOnly("version"), icon));
                    }
                }

                // A track?
                var foundTrack = await CheckDirectoryNodeForTrack(directory, cancellation);

                if (foundTrack != null)
                {
                    return(foundTrack);
                }

                // Or maybe a showroom?
                var uiShowroom = ui.GetSubFile(@"ui_showroom.json");
                if (uiShowroom != null)
                {
                    var icon = await(directory.GetSubFile(@"preview.jpg")?.Info.ReadAsync() ?? Task.FromResult((byte[])null));
                    cancellation.ThrowIfCancellationRequested();

                    var data = await uiShowroom.Info.ReadAsync() ?? throw new MissingContentException();

                    var parsed     = JsonExtension.Parse(data.ToUtf8String());
                    var showroomId = directory.Name ??
                                     directory.Files.Where(x => x.NameLowerCase.EndsWith(@".kn5")).OrderByDescending(x => x.Info.Size)
                                     .FirstOrDefault()?.NameLowerCase.ApartFromLast(@".kn5");
                    if (showroomId != null)
                    {
                        return(new ShowroomContentEntry(directory.Key ?? "", showroomId,
                                                        parsed.GetStringValueOnly("name"), parsed.GetStringValueOnly("version"), icon));
                    }
                }
            }
            else
            {
                // Another case for showrooms
                if (directory.Name != null &&
                    directory.HasSubFile(directory.Name + @".kn5") &&
                    directory.HasSubFile(@"colorCurves.ini") && directory.HasSubFile(@"ppeffects.ini"))
                {
                    var icon = directory.HasSubFile(@"preview.jpg")
                            ? await(directory.GetSubFile(@"preview.jpg")?.Info.ReadAsync() ?? throw new MissingContentException())
                            : null;
                    cancellation.ThrowIfCancellationRequested();
                    return(new ShowroomContentEntry(directory.Key ?? "", directory.Name ?? throw new ArgumentException(), iconData: icon));
                }
            }

            var uiTrackSkin = directory.GetSubFile("ui_track_skin.json");

            if (uiTrackSkin != null && TracksManager.Instance != null)
            {
                var icon = await(directory.GetSubFile("preview.png")?.Info.ReadAsync() ?? Task.FromResult((byte[])null));
                cancellation.ThrowIfCancellationRequested();

                var data = await uiTrackSkin.Info.ReadAsync() ?? throw new MissingContentException();

                var parsed  = JsonExtension.Parse(data.ToUtf8String());
                var skinId  = parsed.GetStringValueOnly("id") ?? directory.Name;
                var trackId = parsed.GetStringValueOnly("track");
                var name    = parsed.GetStringValueOnly("name");

                if (skinId != null && trackId != null)
                {
                    return(new TrackSkinContentEntry(directory.Key ?? "", skinId, trackId, name,
                                                     parsed.GetStringValueOnly("version"), icon));
                }
            }

            if (directory.HasSubFile("settings.ini"))
            {
                var kn5 = directory.Files.Where(x => x.NameLowerCase.EndsWith(@".kn5")).ToList();
                var id  = directory.Name;
                if (id != null)
                {
                    if (kn5.Any(x => x.NameLowerCase.ApartFromLast(@".kn5") == directory.NameLowerCase))
                    {
                        var icon = await(directory.GetSubFile("preview.jpg")?.Info.ReadAsync() ?? Task.FromResult((byte[])null));
                        cancellation.ThrowIfCancellationRequested();

                        return(new ShowroomContentEntry(directory.Key ?? "", id,
                                                        AcStringValues.NameFromId(id), null, icon));
                    }
                }
            }

            var weatherIni = directory.GetSubFile("weather.ini");

            if (weatherIni != null)
            {
                var icon = await(directory.GetSubFile("preview.jpg")?.Info.ReadAsync() ?? Task.FromResult((byte[])null));
                cancellation.ThrowIfCancellationRequested();

                var data = await weatherIni.Info.ReadAsync() ?? throw new MissingContentException();

                var parsed = IniFile.Parse(data.ToUtf8String());

                var name = parsed["LAUNCHER"].GetNonEmpty("NAME");
                if (name != null)
                {
                    var id = directory.Name ?? name;
                    return(new WeatherContentEntry(directory.Key ?? "", id, name, icon));
                }
            }

            var uiCarSkin = directory.GetSubFile("ui_skin.json");

            if ((uiCarSkin != null || directory.HasSubFile("preview.jpg") && directory.HasSubFile("livery.png")) &&
                CarsManager.Instance != null /* for crawlers only */)
            {
                var icon = await(directory.GetSubFile("livery.png")?.Info.ReadAsync() ?? Task.FromResult((byte[])null));
                cancellation.ThrowIfCancellationRequested();

                string carId;
                var    skinFor = await(directory.GetSubFile("cm_skin_for.json")?.Info.ReadAsync() ?? Task.FromResult((byte[])null));
                if (skinFor != null)
                {
                    carId = JsonExtension.Parse(skinFor.ToUtf8String())[@"id"]?.ToString();
                }
                else
                {
                    carId = _installationParams.CarId;

                    if (carId == null && directory.Parent?.NameLowerCase == "skins")
                    {
                        carId = directory.Parent.Parent?.Name;
                    }

                    if (carId == null)
                    {
                        carId = AcContext.Instance.CurrentCar?.Id;
                    }
                }

                if (carId == null)
                {
                    throw new Exception("Can’t figure out car’s ID");
                }

                var skinId = directory.Name;
                if (skinId != null)
                {
                    string name;
                    if (uiCarSkin != null)
                    {
                        var data = await uiCarSkin.Info.ReadAsync() ?? throw new MissingContentException();

                        var parsed = JsonExtension.Parse(data.ToUtf8String());
                        name = parsed.GetStringValueOnly("name");
                    }
                    else
                    {
                        name = AcStringValues.NameFromId(skinId);
                    }

                    return(new CarSkinContentEntry(directory.Key ?? "", skinId, carId, name, icon));
                }
            }

            // New textures
            if (directory.NameLowerCase == "damage" && directory.HasSubFile("flatspot_fl.png"))
            {
                return(new TexturesConfigEntry(directory.Key ?? "", directory.Name ?? @"damage"));
            }

            if (directory.Parent?.NameLowerCase == "crew_brand" && directory.HasSubFile("Brands_Crew.dds") && directory.HasSubFile("Brands_Crew.jpg") &&
                directory.HasSubFile("Brands_Crew_NM.dds"))
            {
                return(new CrewBrandEntry(directory.Key ?? "", directory.Name ?? @"unknown"));
            }

            if (directory.Parent?.NameLowerCase == "crew_helmet" && directory.HasSubFile("Crew_HELMET_Color.dds"))
            {
                return(new CrewHelmetEntry(directory.Key ?? "", directory.Name ?? @"unknown"));
            }

            // TODO: More driver and crew textures

            if (directory.NameLowerCase == "clouds" && directory.Files.Any(
                    x => (x.NameLowerCase.StartsWith(@"cloud") || directory.Parent?.NameLowerCase == "texture") && x.NameLowerCase.EndsWith(@".dds")))
            {
                return(new TexturesConfigEntry(directory.Key ?? "", directory.Name ?? @"clouds"));
            }

            if (directory.NameLowerCase == "clouds_shared" && directory.Files.Any(
                    x => (x.NameLowerCase.StartsWith(@"cloud") || directory.Parent?.NameLowerCase == "texture") && x.NameLowerCase.EndsWith(@".dds")))
            {
                return(new TexturesConfigEntry(directory.Key ?? "", directory.Name ?? @"clouds_shared"));
            }

            if (directory.NameLowerCase == "people" && (directory.HasSubFile("crowd_sit.dds") || directory.HasSubFile("people_sit.dds")))
            {
                return(new TexturesConfigEntry(directory.Key ?? "", directory.Name ?? @"people"));
            }

            if (directory.HasSubFile(PatchHelper.MainFileName) && directory.HasSubDirectory("extension"))
            {
                var    dwrite    = directory.GetSubFile(PatchHelper.MainFileName);
                var    extension = directory.GetSubDirectory("extension");
                var    manifest  = directory.GetSubDirectory("extension")?.GetSubDirectory("config")?.GetSubFile("data_manifest.ini");
                string version;
                if (manifest != null)
                {
                    var data = await manifest.Info.ReadAsync() ?? throw new MissingContentException();

                    version = IniFile.Parse(data.ToUtf8String())["VERSION"].GetNonEmpty("SHADERS_PATCH");
                }
                else
                {
                    var description = directory.GetSubFile("description.jsgme");
                    if (description != null)
                    {
                        var data = await description.Info.ReadAsync() ?? throw new MissingContentException();

                        version = Regex.Match(data.ToUtf8String(), @"(?<=v)\d.*").Value?.TrimEnd('.').Or(null);
                    }
                    else
                    {
                        var parent = directory;
                        while (parent.Parent?.Name != null)
                        {
                            parent = parent.Parent;
                        }
                        version = parent.Name != null?Regex.Match(parent.Name, @"(?<=v)\d.*").Value?.TrimEnd('.').Or(null) : null;
                    }
                }

                return(new ShadersPatchEntry(directory.Key ?? "", new[] { dwrite.Key, extension.Key }, version));
            }

            if (directory.NameLowerCase == "__gbwsuite")
            {
                return(new CustomFolderEntry(directory.Key ?? "", new[] { directory.Key }, "GBW scripts", "__gbwSuite"));
            }

            if (directory.HasSubFile("weather.lua") && directory.Parent.NameLowerCase == "weather")
            {
                return(new CustomFolderEntry(directory.Key ?? "", new[] { directory.Key }, $"Weather FX script “{AcStringValues.NameFromId(directory.Name)}”",
                                             Path.Combine(AcRootDirectory.Instance.RequireValue, "extension", "weather", directory.Name), 1e5));
            }

            if (directory.HasSubFile("controller.lua") && directory.Parent.NameLowerCase == "weather-controllers")
            {
                return(new CustomFolderEntry(directory.Key ?? "", new[] { directory.Key },
                                             $"Weather FX controller “{AcStringValues.NameFromId(directory.Name)}”",
                                             Path.Combine(AcRootDirectory.Instance.RequireValue, "extension", "weather-controllers", directory.Name), 1e5));
            }

            // Mod
            if (directory.Parent?.NameLowerCase == "mods" &&
                (directory.HasAnySubDirectory("content", "apps", "system", "launcher", "extension") || directory.HasSubFile(PatchHelper.MainFileName)))
            {
                var name = directory.Name;
                if (name != null && directory.GetSubDirectory("content")?.GetSubDirectory("tracks")?.Directories.Any(
                        x => x.GetSubDirectory("skins")?.GetSubDirectory("default")?.GetSubFile("ui_track_skin.json") != null) != true)
                {
                    var description = directory.Files.FirstOrDefault(x => x.NameLowerCase.EndsWith(@".jsgme"));
                    if (description == null && directory.HasSubDirectory("documentation"))
                    {
                        description = directory.GetSubDirectory("documentation")?.Files.FirstOrDefault(x => x.NameLowerCase.EndsWith(@".jsgme"));
                    }

                    if (description != null)
                    {
                        var data = await description.Info.ReadAsync() ?? throw new MissingContentException();

                        return(new GenericModConfigEntry(directory.Key ?? "", name, data.ToUtf8String()));
                    }

                    return(new GenericModConfigEntry(directory.Key ?? "", name));
                }
            }

            return(null);
        }
Exemplo n.º 30
0
 public static string NameFromId([NotNull] string id)
 {
     return(AcStringValues.NameFromId(IdFix.Replace(id, "")));
 }