/// <summary>Load skin assets into AnimalSkinner</summary> private void LoadAssets() { // Gather handled types string validTypes = string.Join(", ", ModApi.GetHandledAllTypes()); foreach (FileInfo file in new DirectoryInfo(Path.Combine(this.Helper.DirectoryPath, "assets", "skins")).EnumerateFiles()) { // Check extension of file is handled by AnimalSkinner string extension = Path.GetExtension(file.Name); if (!this.ValidExtensions.Contains(extension)) { this.Monitor.Log($"Ignored skin `assets/skins/{file.Name}` with invalid extension (extension must be one of type {string.Join(", ", this.ValidExtensions)})", LogLevel.Warn); continue; } // Parse file name string[] nameParts = Path.GetFileNameWithoutExtension(file.Name).Split(new[] { '_' }, 2); string type = Sanitize(nameParts[0]); // Ensure creature type is handled by AnimalSkinner if (!PetAssets.ContainsKey(type) && !HorseAssets.ContainsKey(type) && !AnimalAssets.ContainsKey(type)) { this.Monitor.Log($"Ignored skin `assets/skins/{file.Name}` with invalid naming convention (can't parse {nameParts[0]} as an animal, pet, or horse. Expected one of type: {validTypes})", LogLevel.Warn); continue; } // Ensure both a type and skin ID can be found in the file name if (nameParts.Length != 2) { this.Monitor.Log($"Ignored skin `assets/skins/{file.Name} with invalid naming convention (no skin ID found)", LogLevel.Warn); continue; } // Ensure the skin ID is a number int skinID = 0; if (nameParts.Length == 2 && !int.TryParse(nameParts[1], out skinID)) { this.Monitor.Log($"Ignored skin `assets/skins/{file.Name}` with invalid skin ID (can't parse {nameParts[1]} as a number)", LogLevel.Warn); continue; } // Ensure the skin ID is not 0 or negative if (skinID <= 0) { this.Monitor.Log($"Ignored skin `assets/skins/{file.Name}` with skin ID of less than or equal to 0. Skins must have an ID of at least 1."); } // File naming is valid, add asset into system string assetKey = this.Helper.Content.GetActualAssetKey(Path.Combine("assets", "skins", extension.Equals("xnb") ? Path.Combine(Path.GetDirectoryName(file.Name), Path.GetFileNameWithoutExtension(file.Name)) : file.Name)); if (AnimalAssets.ContainsKey(type)) { AnimalAssets[type].Add(new AnimalSkin(type, skinID, assetKey)); } else if (HorseAssets.ContainsKey(type)) { HorseAssets[type].Add(new AnimalSkin(type, skinID, assetKey)); } else { PetAssets[type].Add(new AnimalSkin(type, skinID, assetKey)); } } // Sort each list AnimalSkin.Comparer comp = new AnimalSkin.Comparer(); foreach (string type in AnimalAssets.Keys) { AnimalAssets[type].Sort((p1, p2) => comp.Compare(p1, p2)); } foreach (string type in PetAssets.Keys) { PetAssets[type].Sort((p1, p2) => comp.Compare(p1, p2)); } foreach (string type in HorseAssets.Keys) { HorseAssets[type].Sort((p1, p2) => comp.Compare(p1, p2)); } // Print loaded assets to console StringBuilder summary = new StringBuilder(); summary.AppendLine( "Statistics:\n" + "\n Registered types: " + validTypes + "\n Animal Skins:" ); foreach (KeyValuePair <string, List <AnimalSkin> > pair in ModEntry.AnimalAssets) { if (pair.Value.Count > 0) { summary.AppendLine($" {pair.Key}: {pair.Value.Count} skins ({string.Join(", ", pair.Value.Select(p => Path.GetFileName(p.AssetKey)).OrderBy(p => p))})"); } } summary.AppendLine(" Pet Skins:"); foreach (KeyValuePair <string, List <AnimalSkin> > pair in ModEntry.PetAssets) { if (pair.Value.Count > 0) { summary.AppendLine($" {pair.Key}: {pair.Value.Count} skins ({string.Join(", ", pair.Value.Select(p => Path.GetFileName(p.AssetKey)).OrderBy(p => p))})"); } } summary.AppendLine(" Horse Skins:"); foreach (KeyValuePair <string, List <AnimalSkin> > pair in ModEntry.HorseAssets) { if (pair.Value.Count > 0) { summary.AppendLine($" {pair.Key}: {pair.Value.Count} skins ({string.Join(", ", pair.Value.Select(p => Path.GetFileName(p.AssetKey)).OrderBy(p => p))})"); } } this.Monitor.Log(summary.ToString(), LogLevel.Trace); }