### Create and use KSPe loggers Source: https://context7.com/ksp-modularmanagement/kspe/llms.txt Demonstrates initializing standard, thread-safe, and custom-namespaced loggers, along with usage of various severity levels and conditional logging. ```csharp using KSPe.Util.Log; namespace MyKSPAddon { public class MyPartModule : PartModule { // Create a logger for this type private static readonly Logger Log = Logger.CreateForType(); // Create thread-safe logger for concurrent operations private static readonly Logger ThreadSafeLog = Logger.CreateThreadSafeForType(); // Create logger with custom namespace private static readonly Logger CustomLog = Logger.CreateForType("MyAddon.CustomNamespace"); public override void OnStart(StartState state) { // Different log levels Log.info("Part module started on {0}", this.part.name); Log.detail("Detailed startup info: state={0}", state); Log.trace("Entering OnStart method"); // Very verbose Log.warn("Resource container is empty!"); try { // Your code here } catch (Exception e) { Log.error(e, "Failed to initialize part module"); Log.fatal(this, e); // For critical failures } // Check if logging level is active before expensive operations if (Log.IsLoggable(Level.DETAIL)) { string expensiveDebugInfo = GenerateDebugReport(); Log.detail(expensiveDebugInfo); } // Force log regardless of level Log.force("Important message always shown"); // Set logging level programmatically Log.level = Level.TRACE; } } } ``` -------------------------------- ### Configure KSPe settings via KSPe.cfg Source: https://github.com/ksp-modularmanagement/kspe/blob/mestre/Docs/KSPe.md Define global and per-namespace configuration settings in the KSPe.cfg file located in the PluginData directory. ```text KSPe { DebugMode = False Log { ThreadSafe = False LogLevel = 5 } LOCAL { ModuleManager { DebugMode = False Log { ThreadSafe = False LogLevel = 4 } } TweakScale { DebugMode = False Log { ThreadSafe = False LogLevel = 3 } } } } ``` -------------------------------- ### KSPe Global Configuration File Source: https://context7.com/ksp-modularmanagement/kspe/llms.txt Define global and per-add-on settings in KSPe.cfg. Settings are hierarchical, with per-add-on overrides taking precedence. ```cfg // File: /PluginData/KSPe.cfg KSPe { // Global settings (defaults for all add-ons) DebugMode = False Log { ThreadSafe = False LogLevel = 3 // 0=OFF, 1=ERROR, 2=WARNING, 3=INFO, 4=DETAIL, 5=TRACE } // Per-add-on overrides (use C# namespace as node name) LOCAL { ModuleManager { DebugMode = False Log { ThreadSafe = False LogLevel = 4 // More verbose for ModuleManager } } TweakScale { DebugMode = True // Enable debug features for TweakScale Log { ThreadSafe = True // TweakScale uses threads LogLevel = 3 } } MyKSPAddon { DebugMode = False Log { ThreadSafe = False LogLevel = 5 // Maximum verbosity for debugging } } } } ``` -------------------------------- ### Load Texture with KSPe Utility Source: https://context7.com/ksp-modularmanagement/kspe/llms.txt Use this C# code to load textures (PNG/JPG) with automatic Unity version detection. Ensure KSPe.Util.Image is imported. ```csharp using KSPe.Util.Image; using UnityEngine; namespace MyKSPAddon { public class TextureLoader { public Texture2D LoadTexture(string path) { // Read image bytes (PNG or JPG) byte[] imageData = System.IO.File.ReadAllBytes(path); // Load with automatic Unity version detection Texture2D texture; bool success = File.Load(out texture, imageData); if (success) { Debug.Log($ ``` -------------------------------- ### Perform Sandboxed File Operations with KSPe.IO.File Source: https://context7.com/ksp-modularmanagement/kspe/llms.txt Use the generic File class to perform read, write, and management operations within specific sandboxed locations like Asset, Data, Save, Local, and Temp. ```csharp using KSPe.IO; namespace MyKSPAddon { public class ConfigManager { // Asset files are read-only (in PluginData/Assets folder) public void LoadAssetFile() { // Check if asset exists if (File.Asset.Exists("textures", "button.png")) { // Read binary data byte[] imageData = File.Asset.ReadAllBytes("textures", "button.png"); // Read text file string configText = File.Asset.ReadAllText("defaults.cfg"); // List all config files string[] configs = File.Asset.List("*.cfg", include_subdirs: true); } } // Data files are writable (in PluginData folder) public void SaveDataFile() { // Check existence if (!File.Data.Exists("settings.cfg")) { // Create and write text file using (var writer = File.Data.CreateText("settings.cfg")) { writer.WriteLine("// MyAddon Settings"); writer.WriteLine("enabled = true"); } } // Read all lines string[] lines = File.Data.ReadAllLines("settings.cfg"); // Delete file File.Data.Delete("old_settings.cfg"); // Copy between locations File.Asset.CopyToData("defaults.cfg", "settings.cfg", overwrite: false); } // Save files are per-savegame (in saves//AddOns folder) public void ManageSaveData() { // Only works when a game is loaded if (File.Save.Exists("progress.dat")) { string progress = File.Save.ReadAllText("progress.dat"); } using (var writer = File.Save.CreateText("progress.dat")) { writer.WriteLine("mission_complete = true"); } } // Local files for runtime-generated content (in GameData/__LOCAL folder) public void ManageLocalFiles() { if (File.Local.Exists("generated_part.cfg")) { File.Local.Delete("generated_part.cfg"); } } // Temp files for temporary data public void UseTempFiles() { using (var writer = File.Temp.CreateText("temp_data.txt")) { writer.WriteLine("Temporary content"); } // Copy temp to permanent storage File.Temp.CopyToData("temp_data.txt", "permanent.txt", overwrite: true); } } } ``` -------------------------------- ### KSPe Configuration File Source: https://github.com/ksp-modularmanagement/kspe/blob/mestre/Docs/KSPe.md Defines the structure and parameters for the KSPe.cfg file used to configure logging and debug modes for Add'Ons. ```APIDOC ## KSPe Configuration ### Description Configures KSPe parameters on an Add'On basis via a KSPe.cfg file located in the PluginData directory. ### Parameters - **DebugMode** (boolean) - Optional - A flag to allow activating or suppressing diagnostic features at runtime. Default: False. - **Log.Level** (int) - Optional - Defines the logging level (0=OFF, 1=ERROR, 2=WARNING, 3=INFO, 4=DETAIL, 5=TRACE). Default: 3. - **Log.ThreadSafe** (boolean) - Optional - Activates thread-safe logging routines. Default: False. ### Request Example KSPe { DebugMode = False Log { ThreadSafe = False LogLevel = 5 } LOCAL { Namespace.Name { DebugMode = False Log { ThreadSafe = False LogLevel = 3 } } } } ``` -------------------------------- ### Load Texture from KSPe Asset Source: https://context7.com/ksp-modularmanagement/kspe/llms.txt Load textures by combining KSPe's file system access with its image loading utility. Specify asset path and filename. ```csharp public Texture2D LoadFromAsset() { // Combine with KSPe file system byte[] imageData = KSPe.IO.File.Asset.ReadAllBytes("icons", "toolbar.png"); Texture2D texture; File.Load(out texture, 32, 32, imageData); return texture; } } } ``` -------------------------------- ### Type-Namespaced Configuration Storage with KSPe.IO.Data.ConfigNode Source: https://context7.com/ksp-modularmanagement/kspe/llms.txt Utilize KSPe.IO.Data.ConfigNode for type-namespaced configuration storage, automatically managing file paths based on the type. It allows creating, loading, modifying, and saving configurations with custom names or nested paths. ```csharp using KSPe.IO.Data; namespace MyKSPAddon { public class SettingsManager { public void ManageSettings() { // Create ConfigNode for type (stored in PluginData//MyKSPAddon.SettingsManager.cfg) var config = ConfigNode.ForType(); // Create with custom name var namedConfig = ConfigNode.ForType("UserSettings"); // Create with specific filename var customConfig = ConfigNode.ForType("main", "settings.cfg"); // Create with nested path var nestedConfig = ConfigNode.ForType("data", "config", "prefs.cfg"); // Load existing configuration config.Load(); // Access the underlying ConfigNode ConfigNode node = config.Node; // Modify values node.SetValue("lastUsed", DateTime.Now.ToString(), true); node.SetValue("windowX", 100); node.SetValue("windowY", 200); // Add sub-nodes ConfigNode resourceSettings = node.AddNode("RESOURCES"); resourceSettings.SetValue("fuelType", "LiquidFuel"); resourceSettings.SetValue("amount", 1000); // Save configuration config.Save(); // List all config files for this type string[] allConfigs = ConfigNode.ListForType("*.cfg", subdirs: true); } } } ``` -------------------------------- ### Resolve Directory Paths with KSPe.IO.Hierarchy Source: https://context7.com/ksp-modularmanagement/kspe/llms.txt Use the Hierarchy class to resolve standard KSP directory paths and perform file operations relative to those locations. ```csharp using KSPe.IO; namespace MyKSPAddon { public class PathResolver { public void ResolvePaths() { // Get relative paths to standard directories string gameDataPath = Hierarchy.GAMEDATA.Solve(); // "GameData/" string pluginDataPath = Hierarchy.PLUGINDATA.Solve(); // "PluginData/" string screenshotPath = Hierarchy.SCREENSHOT.Solve(); // "Screenshots/" string savePath = Hierarchy.SAVE.Solve(); // "saves/" string thumbPath = Hierarchy.THUMB.Solve(); // "thumbs/" string localPath = Hierarchy.LOCALDATA.Solve(); // "GameData/__LOCAL/" // Resolve paths with subdirectories string modPath = Hierarchy.GAMEDATA.Solve("MyMod", "Plugins"); // Returns: "GameData/MyMod/Plugins/" // Resolve and create directories if needed string outputPath = Hierarchy.PLUGINDATA.Solve( createDirs: true, "MyMod", "Output", "data.txt" ); // Check if file exists at hierarchy location bool exists = File.Exists(Hierarchy.GAMEDATA, "MyMod", "config.cfg"); // Read from hierarchy location string content = File.ReadAllText(Hierarchy.GAMEDATA, "MyMod", "readme.txt"); // List files in hierarchy string[] files = File.List(Hierarchy.GAMEDATA, "*.cfg", include_subdirs: true, "MyMod"); } } } ``` -------------------------------- ### Module Manager KSP Version Detection Source: https://context7.com/ksp-modularmanagement/kspe/llms.txt Use KSPe's automatic `:NEEDS` tags in Module Manager patches for KSP version-specific logic. Tags are cumulative. ```cfg // Use KSP version tags in Module Manager patches // Tags are cumulative: KSP-1.8 implies KSP-1.7, KSP-1.6, etc. // Apply only to KSP 1.8 and later @PART[*]:HAS[@MODULE[ModuleEngines]]:NEEDS[KSP-1.8] { @MODULE[ModuleEngines] { useAtmCurve = true } } // Apply only to KSP 1.3 through 1.4.x (using negation) @PART[*]:NEEDS[KSP-1.3,!KSP-1.5] { MODULE { name = LegacyCompatModule } } // Apply to KSP 1.10 and later @RESOURCE_DEFINITION[ElectricCharge]:NEEDS[KSP-1.10] { @density = 0 } // Available tags: KSP-1.1, KSP-1.2, KSP-1.3, KSP-1.4, KSP-1.5, // KSP-1.6, KSP-1.7, KSP-1.8, KSP-1.9, KSP-1.10, // KSP-1.11, KSP-1.12 ``` -------------------------------- ### Type-Safe ConfigNode Value Extraction with KSPe.ConfigNodeWithSteroids Source: https://context7.com/ksp-modularmanagement/kspe/llms.txt Use ConfigNodeWithSteroids to load and manipulate KSP ConfigNodes with generic type-safe extraction for primitive types, arrays, and Unity types. It supports default values and provides methods to commit or rollback changes. ```csharp using KSPe; using UnityEngine; namespace MyKSPAddon { public class ConfigLoader { public void LoadConfiguration() { // Load standard ConfigNode ConfigNode rawNode = ConfigNode.Load("GameData/MyMod/config.cfg"); // Wrap with enhanced functionality ConfigNodeWithSteroids config = ConfigNodeWithSteroids.from(rawNode); // Type-safe value extraction int maxParts = config.GetValue("maxParts"); float threshold = config.GetValue("threshold", 0.5f); // with default bool enabled = config.GetValue("enabled", true); string name = config.GetValue("displayName"); // Array extraction int[] allowedIds = config.GetArrayOf("allowedPartIds"); float[] multipliers = config.GetArrayOf("damageMultipliers", new float[] { 1.0f }); // Set array values config.SetArrayOf("resourceIds", new int[] { 1, 2, 3, 4 }); // Unity types are automatically parsed Vector3 position = config.GetValue("spawnPosition"); // Parsed from: spawnPosition = 1.0, 2.5, 3.0 Vector3d precisePosition = config.GetValue("orbitPosition"); Quaternion rotation = config.GetValue("initialRotation"); // Parsed from: initialRotation = 0.0, 0.707, 0.0, 0.707 // Navigate to child nodes ConfigNodeWithSteroids resourceNode = config.GetNode("RESOURCE_SETTINGS"); float fuelRate = resourceNode.GetValue("consumptionRate"); // Commit changes back to source config.Commit(); // Or rollback changes config.Rollback(); } // Example config file format: // SETTINGS // { // maxParts = 100 // threshold = 0.75 // enabled = true // displayName = My Awesome Mod // allowedPartIds = 1, 2, 3, 4, 5 // spawnPosition = 10.0, 25.5, 30.0 // initialRotation = 0.0, 0.707, 0.0, 0.707 // RESOURCE_SETTINGS // { // consumptionRate = 0.5 // } // } } } ``` -------------------------------- ### Monitor Save Game Events Source: https://context7.com/ksp-modularmanagement/kspe/llms.txt Implement SaveGameMonitor.SaveGameLoadedListener to receive notifications when save games are loaded or closed. This helps manage add-on state and data reliably, avoiding timing issues with KSP's built-in events. ```csharp using KSPe.IO; using UnityEngine; namespace MyKSPAddon { public class SaveDataManager : MonoBehaviour, SaveGameMonitor.SaveGameLoadedListener { private void Start() { // Register for save game notifications SaveGameMonitor.Instance.Add(this); // Or register for single notification SaveGameMonitor.Instance.AddSingleShot(this); } private void OnDestroy() { // Clean up listener SaveGameMonitor.Instance.Remove(this); } // Called when a save game is fully loaded and ready public void OnSaveGameLoaded(string saveName) { Debug.Log($"[MyMod] Save game loaded: {saveName}"); // Safe to access save-specific data now LoadModSaveData(); InitializeForSaveGame(); } // Called when returning to main menu or loading different save public void OnSaveGameClosed() { Debug.Log("[MyMod] Save game closed"); // Cleanup save-specific resources SaveCurrentProgress(); ClearSaveSpecificData(); } // Check if save game data is currently valid public void CheckSaveState() { if (SaveGameMonitor.Instance.IsValid) { // Safe to perform save-related operations string currentSave = HighLogic.fetch.GameSaveFolder; } else { Debug.LogWarning("[MyMod] No active save game"); } } private void LoadModSaveData() { } private void InitializeForSaveGame() { } private void SaveCurrentProgress() { } private void ClearSaveSpecificData() { } } } ``` -------------------------------- ### Module Manager Patch Detection Source: https://github.com/ksp-modularmanagement/kspe/blob/mestre/Docs/KSPe.md Details on using KSPe tags for version-specific Module Manager patching. ```APIDOC ## Module Manager Version Detection ### Description Allows patches to detect the KSP Major version using :NEEDS tags. Tags are cumulative (e.g., KSP-1.1 to KSP-1.10). ### Usage - **:NEEDS[KSP-1.3]** - Patch applies for KSP 1.3 and newer. - **:NEEDS[KSP-1.3,!KSP-1.5]** - Restricts patch to KSP versions between 1.3.0 and 1.4.5. ``` -------------------------------- ### Load Texture with Explicit Dimensions Source: https://context7.com/ksp-modularmanagement/kspe/llms.txt Load textures with specified dimensions and control the 'readable' flag. Useful for performance-sensitive loading. ```csharp public Texture2D LoadTextureWithSize(string path, int width, int height) { byte[] imageData = System.IO.File.ReadAllBytes(path); // Load with explicit dimensions and non-readable flag Texture2D texture; bool success = File.Load( out texture, width, height, imageData, markNonReadable: false // Keep readable for further processing ); return success ? texture : null; } ``` -------------------------------- ### Check Module Manager Cache Status Source: https://context7.com/ksp-modularmanagement/kspe/llms.txt Use ModuleManagerTools.IsLoadedFromCache to determine if Module Manager loaded patches from its cache. This is useful for performing certain operations only when patches have been rebuilt. ```csharp using KSPe.Util; namespace MyKSPAddon { [KSPAddon(KSPAddon.Startup.MainMenu, true)] public class SanityChecker : MonoBehaviour { private void Start() { // Check if Module Manager loaded patches from cache if (ModuleManagerTools.IsLoadedFromCache) { Debug.Log("[MyMod] MM loaded from cache - skipping sanity checks"); } else { // Patches were rebuilt - run validation Debug.Log("[MyMod] MM rebuilt patches - running sanity checks"); ValidatePartConfigs(); CheckForConflicts(); } } private void ValidatePartConfigs() { // Perform expensive validation only when patches change foreach (AvailablePart part in PartLoader.LoadedPartsList) { // Validate part configurations } } private void CheckForConflicts() { // Check for mod conflicts only on fresh patch application } } } ``` -------------------------------- ### Module Manager Cache Detection Source: https://github.com/ksp-modularmanagement/kspe/blob/mestre/Docs/KSPe.md API utility to detect if Module Manager patches were loaded from cache. ```APIDOC ## KSPe.Util.ModuleManagerTools.IsLoadedFromCache ### Description Boolean property to check if Module Manager loaded patches from the cache or rebuilt them from scratch. ### Return Value - **true** - Patches loaded from cache. - **false** - Cache was rebuilt. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.