public IEnumerator shutter(string filename) { yield return(true); //doesn't seem to matter what this returns Thread.Sleep(100); //delay before re-opening windows //Application.CaptureScreenshot seems insistant on plonking the picture in KSP_Data, so this next bit relocates the pic to join it's friends in the screenshot folder string origin_path = Paths.joined(KSPUtil.ApplicationRootPath, "KSP_Data", filename); //location where screenshot is created (as a png) string png_path = Paths.joined(CraftManager.screenshot_dir, filename); //location where it will be moved to if (File.Exists((origin_path))) { CraftManager.log("moving file: " + origin_path + " to: " + png_path); File.Move(origin_path, png_path); } else //TODO find less hacky way of solving which Data folder to look in { origin_path = Paths.joined(KSPUtil.ApplicationRootPath, "KSP_x64_Data", filename); //location where screenshot is created (as a png) if (File.Exists((origin_path))) { CraftManager.log("moving file: " + origin_path + " to: " + png_path); File.Move(origin_path, png_path); } } close(); }
public void put() { errors.Clear(); if (CraftManager.main_ui.show_transfer_indicator) { errors.Add("unable to update, another craft is still uploading"); } if (errors.Count == 0) { CraftManager.main_ui.close_update_kerbalx_craft_dialog(); CraftManager.main_ui.show_transfer_indicator = true; CraftManager.main_ui.transfer_is_upload = false; WWWForm craft_data = new WWWForm(); craft_data.AddField("craft_name", craft_name); craft_data.AddField("craft_file", System.IO.File.ReadAllText(craft.path)); craft_data.AddField("part_data", JSONX.toJSON(part_info())); KerbalX.api.update_craft(update_to_id, craft_data, (resp, code) => { if (code == 200) { CraftManager.log("craft updated OK"); KerbalX.api.fetch_existing_craft((empty_resp, status_code) => { CraftManager.main_ui.close_upload_interface(); }); } else { CraftManager.log("craft update failed"); } CraftManager.main_ui.show_transfer_indicator = false; }); } }
internal static void cache_game_parts() { CraftManager.log("caching game parts"); locked_parts.Clear(); List <string> part_names = new List <string>(); foreach (AvailablePart part in PartLoader.LoadedPartsList) { if (!part_data.ContainsKey(part.name)) { part_data.Add(part.name, part); } part_names.AddUnique(part.name); if (!ResearchAndDevelopment.PartTechAvailable(part)) { locked_parts.AddUnique(part.name); } } //Make a string containing all the installed parts and the data from LoaderInfo in the save file and //then generate a checksum from it. This is used as a signature of the installed setup which will change //if the installed mods are changed enabling craft to disregard cached data after a change in mod setup. part_names.Sort(); string s = String.Join("", part_names.ToArray()); string lf = ""; try{ ConfigNode save_data = ConfigNode.Load(Paths.joined(CraftManager.ksp_root, "saves", HighLogic.SaveFolder, "persistent.sfs")); ConfigNode loader_info = save_data.GetNode("GAME").GetNode("LoaderInfo"); lf = loader_info.ToString(); } catch (Exception e) { CraftManager.log("Failed to read loaderinfo " + e.Message); } installed_part_sig = Checksum.digest(s + lf); }
private void load() { craft_data.Clear(); ConfigNode nodes = ConfigNode.Load(cache_path); if (nodes.GetValue("craft_manager_version") == CraftManager.version) { ConfigNode craft_nodes = nodes.GetNode("CraftData"); foreach (ConfigNode node in craft_nodes.nodes) { try{ string path = sanitize_path(node.GetValue("path")); if (!craft_data.ContainsKey(path)) { craft_data.Add(node.GetValue("path"), node); } } catch (Exception e) { CraftManager.log("failed to add " + node.GetValue("path") + "\n" + e.Message); } } } else { CraftManager.log("cache was generated by another version of CraftManager, resetting cache"); } }
//Button Actions //Action for main interface button private void toggle_main_ui() { if (CraftManager.main_ui) { CraftManager.main_ui.toggle(); } else { CraftManager.log("Main UI has not been started"); } }
//Loads Tag data from confignode file for a given save or for all saves if "<all_saves>" is given //If a save does not have a craft.tags file it copies the default.tags file into the save. //Will also instanciate an instance of Tags if one does not already exist. public static void load(string save_name) { if (Tags.instance == null) { new Tags(); } List <string> save_dirs = new List <string> { save_name }; Tags.instance.data.Clear(); if (save_name == CMBrowser.all_saves_ref) { save_dirs = CraftData.save_names; } foreach (string save_dir in save_dirs) { CraftManager.log("loading tags for " + save_dir); if (!File.Exists(tag_file_path(save_dir))) { FileInfo default_tags = new FileInfo(Paths.joined(CraftManager.ksp_root, "GameData", "CraftManager", "default.tags")); //TODO handle case where default.tags file is not present. default_tags.CopyTo(tag_file_path(save_dir)); } ConfigNode raw_data = ConfigNode.Load(tag_file_path(save_dir)); ConfigNode tag_nodes = raw_data.GetNode("TAGS"); foreach (ConfigNode tag_node in tag_nodes.nodes) { string tag_name = tag_node.GetValue("tag_name"); Tag tag = Tags.find_or_create_by(tag_name, save_dir, false); if (tag_node.HasNode("RULE")) { ConfigNode rule_node = tag_node.GetNode("RULE"); bool rule_added = tag.set_rule(rule_node.GetValue("attribute"), rule_node.GetValue("comparator"), rule_node.GetValue("value")); if (!rule_added) { CraftManager.log("failed to load rule for tag: " + tag_name); } } else { string[] craft = tag_node.GetValues("craft"); foreach (string craft_ref in craft) { tag.craft.AddUnique(craft_ref); } } } } Tags.update_lists(); }
private void grab_screenshot() { hide(); string filename = "screenshot - " + string.Format("{0:yyyy-MM-dd_hh-mm-ss}", DateTime.Now) + ".png"; CraftManager.log("grabbing screenshot: " + filename); // Application.CaptureScreenshot(filename); ScreenCapture.CaptureScreenshot(filename); StartCoroutine(shutter(filename)); //shutter re-opens the windows. well, it's kinda the exact opposite of what a shutter does, but yeah....whatever }
//Takes a CraftData craft object and if the cached data contains a matching path AND the checksum value matches //then the craft's properties are populated from the ConfigNode in the cache. Returns true if matching data was //found, otherwise returns false, in which case the data will have to be interpreted from the .craft file. internal bool try_fetch(CraftData craft) { string path = sanitize_path(craft.path); if (craft_data.ContainsKey(path) && craft_data[path].GetValue("checksum") == craft.checksum && craft_data[path].GetValue("part_sig") == installed_part_sig) { try{ // CraftManager.log("loading from CACHE: " + Path.GetFileNameWithoutExtension(path)); CraftData.cache_load_count += 1; //increment count of craft loaded from cache ConfigNode node = craft_data[path]; foreach (var prop in craft.GetType().GetProperties()) { if (prop.CanWrite) { var node_value = node.GetValue(prop.Name); if (!String.IsNullOrEmpty(node_value)) { var type = prop.GetValue(craft, null); if (type is float) { prop.SetValue(craft, float.Parse(node_value), null); } else if (type is int) { prop.SetValue(craft, int.Parse(node_value), null); } else if (type is bool) { prop.SetValue(craft, bool.Parse(node_value), null); } else { prop.SetValue(craft, node_value, null); } } } } if (node.HasValue("locked_parts")) { craft.locked_parts_checked = true; } return(true); } catch (Exception e) { CraftManager.log("try_fetch failed: " + e.Message + "\n" + e.StackTrace); return(false); } } else { return(false); } }
internal static IEnumerator <bool> load_cache() { yield return(true); if (!File.Exists(CraftDataCache.cache_path)) { CraftManager.log("pre-generating craft data cache"); CraftData.load_craft_from_files(CraftManager.main_ui.active_save_dir); } else if (CraftData.cache == null) { CraftData.cache = new CraftDataCache(); } }
//Bind events to add buttons to the toolbar private void add_main_icon_to_toolbar() { ApplicationLauncher.Instance.AddOnHideCallback(this.toolbar_on_hide); //bind events to close guis when toolbar hides CraftManager.log("Adding main icon to toolbar"); if (!CraftManager.main_ui_toolbar_button) { CraftManager.main_ui_toolbar_button = ApplicationLauncher.Instance.AddModApplication( toggle_main_ui, toggle_main_ui, main_btn_hover_on, main_btn_hover_off, null, null, ApplicationLauncher.AppScenes.VAB | ApplicationLauncher.AppScenes.SPH, StyleSheet.assets["ui_toolbar_btn"] ); } }
public static void load_stock_craft_from_files() { CraftManager.log("loading stock craft"); string[] craft_file_paths = Directory.GetFiles(Paths.joined(CraftManager.ksp_root, "Ships"), "*.craft", SearchOption.AllDirectories); for (int i = 0; i < craft_file_paths.Length; i++) { new CraftData(craft_file_paths[i], true); } if (CraftManager.main_ui) { CraftManager.main_ui.stock_craft_loaded = true; } ; }
//remove any existing buttons from the toolbar private void remove_from_toolbar() { if (CraftManager.main_ui_toolbar_button || CraftManager.quick_tag_toolbar_button) { CraftManager.log("Removing buttons from toolbar"); } if (CraftManager.main_ui_toolbar_button) { ApplicationLauncher.Instance.RemoveModApplication(CraftManager.main_ui_toolbar_button); CraftManager.main_ui_toolbar_button = null; } if (CraftManager.quick_tag_toolbar_button) { ApplicationLauncher.Instance.RemoveModApplication(CraftManager.quick_tag_toolbar_button); CraftManager.quick_tag_toolbar_button = null; } }
//returns a new instance of KerbalXUploadData for the given craft or returns an existing instance if one has already been created. public static KerbalXUploadData prepare_for(CraftData for_craft) { KerbalXUploadData data; if (upload_data_store.ContainsKey(for_craft.path)) { CraftManager.log("loading upload data for: " + for_craft.name); data = upload_data_store[for_craft.path]; } else { CraftManager.log("creating upload data for: " + for_craft.name); data = new KerbalXUploadData(for_craft); upload_data_store.Add(for_craft.path, data); } return(data); }
public void post() { if (is_valid) { CraftManager.main_ui.show_transfer_indicator = true; CraftManager.main_ui.transfer_is_upload = true; WWWForm craft_data = new WWWForm(); craft_data.AddField("craft_name", craft_name); craft_data.AddField("craft_style", craft_type); craft_data.AddField("craft_file", System.IO.File.ReadAllText(craft.path)); craft_data.AddField("part_data", JSONX.toJSON(part_info())); craft_data.AddField("action_groups", JSONX.toJSON(action_groups)); craft_data.AddField("hash_tags", hash_tags); int pic_count = 0; foreach (Image image in images) { craft_data.AddField("images[image_" + pic_count++ + "]", Convert.ToBase64String(image.read_as_jpg())); // craft_data.AddField("image_urls[url_" + pic_count++ + "]", "https://i.imgur.com/nSUkIe0.jpg"); } KerbalX.api.upload_craft(craft_data, (resp, code) => { // var resp_data = JSON.Parse(resp); if (code == 200) { CraftManager.log("craft uploaded OK"); KerbalX.api.fetch_existing_craft((empty_resp, status_code) => { //refresh remote craft info craft.matching_remote_ids = null; CraftManager.main_ui.close_upload_interface(); }); } else { CraftManager.log("craft upload failed"); } //return UI to craft list mode and show upload complete dialog. CraftManager.main_ui.show_transfer_indicator = false; // CraftManager.main_ui.unlock_ui(); CraftManager.main_ui.upload_complete_dialog(code, JSON.Parse(resp)); }); } }
private void set_window_pos_from_settings() { try{ string pos = CraftManager.settings.get("quick_tag_pos"); if (pos == "auto") { set_window_pos(); } else { int x = int.Parse(pos.Split(',')[0]); int y = int.Parse(pos.Split(',')[1]); set_window_pos(x, y); } } catch (Exception e) { CraftManager.log("failed to read setting for quick tag position, " + e.Message + "\ndefaulting to auto position"); set_window_pos(); save_window_pos(); } }
internal CraftDataCache() { CraftManager.log("Initializing Cache"); CraftManager.settings.ensure_plugin_data_dir_exists(); if (File.Exists(cache_path)) { CraftManager.log("loading persistent cache from file"); try{ load(); } catch (Exception e) { CraftManager.log("Failed to load cache " + e.Message); } } if (part_data.Count == 0) { cache_game_parts(); } CraftManager.log("Cache Ready"); }
internal static void ensure_ship_folders_exist(string save_dir) { string save_path = Paths.joined(CraftManager.ksp_root, "saves", save_dir); CraftManager.log("checking save folders in " + save_path); if (!Directory.Exists(Paths.joined(save_path, "Subassemblies"))) { Directory.CreateDirectory(Paths.joined(save_path, "Subassemblies")); } if (!Directory.Exists(Paths.joined(save_path, "Ships"))) { Directory.CreateDirectory(Paths.joined(save_path, "Ships")); } if (!Directory.Exists(Paths.joined(save_path, "Ships", "VAB"))) { Directory.CreateDirectory(Paths.joined(save_path, "Ships", "VAB")); } if (!Directory.Exists(Paths.joined(save_path, "Ships", "SPH"))) { Directory.CreateDirectory(Paths.joined(save_path, "Ships", "SPH")); } }
public static void load_craft_from_files(string save_dir = null) { if (cache == null) { cache = new CraftDataCache(); } file_load_count = 0; cache_load_count = 0; string[] craft_file_paths; if (save_dir == null) { craft_file_paths = Directory.GetFiles(Paths.joined(CraftManager.ksp_root, "saves"), "*.craft", SearchOption.AllDirectories); } else { craft_file_paths = Directory.GetFiles(Paths.joined(CraftManager.ksp_root, "saves", save_dir), "*.craft", SearchOption.AllDirectories); } all_craft.Clear(); for (int i = 0; i < craft_file_paths.Length; i++) { new CraftData(craft_file_paths[i]); } if (CraftManager.main_ui && !CraftManager.main_ui.exclude_stock_craft) { load_stock_craft_from_files(); } if (cache_load_count > 0) { CraftManager.log("Loaded " + cache_load_count + " craft from cache"); } if (file_load_count > 0) { CraftManager.log("Loaded " + file_load_count + " craft from file"); } }
public string delete() { if (File.Exists(path)) { CraftManager.log("Deleting Craft: " + path); File.Delete(path); FileInfo thumbnail_file = new FileInfo(thumbnail_path()); if (thumbnail_file.Exists) { thumbnail_file.Delete(); } Tags.untag_craft(this); if (CraftManager.main_ui) { CraftManager.main_ui.refresh(); } return("200"); } else { return("error 404 - file not found: " + path); } }