private static void AddCustomTabs(ref CraftNode nodes, List <CustomCraftTab> customTabs, CraftScheme scheme) { foreach (var tab in customTabs) { if (tab.Scheme != scheme) { continue; } var path = tab.Path.SplitByChar('/'); var currentNode = default(TreeNode); currentNode = nodes; for (int i = 0; i < path.Length; i++) { var currentPath = path[i]; var node = currentNode[currentPath]; if (node == null) { var newNode = new CraftNode(currentPath, TreeAction.Expand, TechType.None); currentNode.AddNode(new TreeNode[] { newNode }); node = newNode; } currentNode = node; } } }
public static void Postfix(ref CraftNode __result) { foreach (var craftNode2 in customCraftNodes) { var path = craftNode2.Key.SplitByChar('/'); var currentNode = default(TreeNode); currentNode = __result; for (int i = 0; i < path.Length; i++) { var currentPath = path[i]; if (i == (path.Length - 1)) { break; } currentNode = currentNode[currentPath]; } currentNode.AddNode(new TreeNode[] { new CraftNode(path[path.Length - 1], TreeAction.Craft, craftNode2.Value) }); } }
/// <summary> /// Populates a new ModCraftTreeRoot from a CraftNode tree. /// </summary> /// <param name="tree">The tree to create the ModCraftTreeRoot from.</param> /// <param name="root"></param> internal static void CreateFromExistingTree(CraftNode tree, ref ModCraftTreeLinkingNode root) { foreach (CraftNode node in tree) { if (node.action == TreeAction.Expand) { ModCraftTreeTab tab = root.AddTabNode(node.id); var thing = (ModCraftTreeLinkingNode)tab; CreateFromExistingTree(node, ref thing); } if (node.action == TreeAction.Craft) { var techType = TechType.None; TechTypeExtensions.FromString(node.id, out techType, false); if (node.id == "SeamothHullModule2") { techType = TechType.VehicleHullModule2; } else if (node.id == "SeamothHullModule3") { techType = TechType.VehicleHullModule3; } root.AddCraftingNode(techType); } } }
/// <summary> /// Swaps the start building of the craft. /// </summary> public static void SwapBuildingOfSelectedCraft(CraftNode craftNode) { string fullPath = KSPPathHelper.GetAbsolutePath(craftNode.FilePath); if (File.Exists(fullPath)) { string newType = GetOtherBuilding(craftNode.Type); string newPath = GetNewPath(craftNode, newType); string allText = File.ReadAllText(fullPath); if (!ChangeParameter(ref allText, craftNode.Name, "type", craftNode.Type, newType)) { return; } File.WriteAllText(fullPath, allText); File.Move(fullPath, newPath); Messenger.AddInfo(string.Format(Messages.MSG_BUILDING_OF_CRAFT_0_SWAPPED_1_2, craftNode.Name, craftNode.Type, newType)); craftNode.Type = newType; craftNode.FilePath = newPath; View.InvalidateView(); } }
private static void PatchNodes(ref CraftNode nodes, List <CustomCraftNode> customNodes, CraftScheme scheme) { foreach (var customNode in customNodes) { if (customNode.Scheme != scheme) { continue; } var path = customNode.Path.SplitByChar('/'); var currentNode = default(TreeNode); currentNode = nodes; for (int i = 0; i < path.Length; i++) { var currentPath = path[i]; if (i == (path.Length - 1)) { break; } currentNode = currentNode[currentPath]; } currentNode.AddNode(new TreeNode[] { new CraftNode(path[path.Length - 1], TreeAction.Craft, customNode.TechType) }); } }
protected CustomCraftTreeNode(string name, TreeAction action, TechType techType) { Name = name; Action = action; TechType = techType; // This is the actual class used for the real CraftTree CraftNode = new CraftNode(Name, Action, TechType); }
private static void RemoveNodes(ref CraftNode nodes, List <Node> nodesToRemove, CraftTree.Type scheme) { // This method can be used to both remove single child nodes, thus removing one recipe from the tree. // Or it can remove entire tabs at once, removing the tab and all the recipes it contained in one go. foreach (Node nodeToRemove in nodesToRemove) { // Not for this fabricator. Skip. if (nodeToRemove.Scheme != scheme) { continue; } if (nodeToRemove.Path == null || nodeToRemove.Path.Length == 0) { Logger.Warn($"An empty path in {nameof(RemoveNodes)} for '{scheme}' was skipped"); continue; } // Get the names of each node in the path to traverse tree until we reach the node we want. TreeNode currentNode = default; currentNode = nodes; // Travel the path down the tree. string currentPath = null; for (int step = 0; step < nodeToRemove.Path.Length; step++) { currentPath = nodeToRemove.Path[step]; if (step > nodeToRemove.Path.Length) { break; } currentNode = currentNode[currentPath]; } // Safty checks. if (currentNode != null && currentNode.id == currentPath) { if (currentNode.parent == null) { Logger.Warn($"Skipped removing craft tree node in {nameof(RemoveNodes)} for '{scheme}'. Could not identify the parent node."); } else { currentNode.Clear(); // Remove all child nodes (if any) currentNode.parent.RemoveNode(currentNode); // Remove the node from its parent } } } }
public static void FabricatorSchemePostfix(ref CraftNode __result) { AddCustomTabs(ref __result, customTabs, CraftScheme.Fabricator); PatchNodes(ref __result, customNodes, CraftScheme.Fabricator); var list = new List <CustomCraftNode>(); foreach (var node in customCraftNodes) { list.Add(new CustomCraftNode(node.Value, CraftScheme.Fabricator, node.Key)); } PatchNodes(ref __result, list, CraftScheme.Fabricator); }
private CraftTree CreateCraftingTree() { if (craftTree == null) { Dictionary <string, string> langLines = Language.main.strings; Dictionary <string, Atlas.Sprite> group = SpriteManager.groups[SpriteManager.Group.Category]; Dictionary <string, Atlas.Sprite> atlas = Atlas.GetAtlas("Categories").nameToSprite; CraftNode fab = CraftTree.FabricatorScheme(); CloneTabDetails(FabricatorScheme, fab, ref langLines, ref group, ref atlas); CraftNode wb = CraftTree.WorkbenchScheme(); CloneTabDetails(WorkBenchScheme, wb, ref langLines, ref group, ref atlas); CraftNode su = CraftTree.SeamothUpgradesScheme(); CloneTabDetails(SeamothUpgradesScheme, su, ref langLines, ref group, ref atlas); CraftNode map = CraftTree.MapRoomSheme(); CloneTabDetails(MapRoomScheme, map, ref langLines, ref group, ref atlas); CraftNode cy = CraftTree.CyclopsFabricatorScheme(); CloneTabDetails(CyclopsFabScheme, cy, ref langLines, ref group, ref atlas); CraftNode aioRoot = new CraftNode("Root").AddNode(fab, wb, su, map, cy); Type smlCTPatcher = typeof(CraftTreeHandler).Assembly.GetType("SMLHelper.V2.Patchers.CraftTreePatcher"); var customTrees = (Dictionary <CraftTree.Type, ModCraftTreeRoot>)smlCTPatcher.GetField("CustomTrees", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null); foreach (KeyValuePair <CraftTree.Type, ModCraftTreeRoot> entry in customTrees) { if (entry.Key == this.TreeTypeID) { continue; } CraftTree tree = entry.Value.CraftTreeCreation.Invoke(); CraftNode root = tree.nodes; string scheme = entry.Key.ToString(); CloneTabDetails(scheme, root, ref langLines, ref group, ref atlas); CloneTopLevelModTab(scheme, ref langLines, ref group); aioRoot.AddNode(root); } craftTree = new CraftTree(AioFabScheme, aioRoot); } return(craftTree); }
private void tvCrafts_DrawControl(object o, DrawEventArgs e) { CraftNode node = (CraftNode)e.Node.Tag; if (e.Text != node.Name) { return; } e.TextColor = Color.Black; if (node.IsInvalidOrHasInvalidChilds) { e.TextColor = Color.FromArgb(255, 0, 0); } }
/// <summary> /// Returns the new path for the craft. /// </summary> /// <param name="craftNode">The CraftNode to get a new path for.</param> /// <param name="newType">the new type of the craft.</param> /// <returns>The new path for the craft.</returns> private static string GetNewPath(CraftNode craftNode, string newType) { string fullPath = KSPPathHelper.GetAbsolutePath(craftNode.FilePath); int index = fullPath.ToLower().IndexOf(Path.DirectorySeparatorChar + craftNode.Type.ToLower() + Path.DirectorySeparatorChar); if (index > -1) { string start = fullPath.Substring(0, index + 1); string end = fullPath.Substring(index + 5); return(Path.Combine(Path.Combine(start, newType.ToUpper()), end)); } else { return(fullPath); } }
/// <summary> /// Populates a new ModCraftTreeRoot from a CraftNode tree. /// </summary> /// <param name="tree">The tree to create the ModCraftTreeRoot from.</param> /// <param name="root"></param> internal static void CreateFromExistingTree(CraftNode tree, ref ModCraftTreeLinkingNode root) { foreach (CraftNode node in tree) { if (node.action == TreeAction.Expand) { ModCraftTreeTab tab = root.AddTabNode(node.id); var thing = (ModCraftTreeLinkingNode)tab; CreateFromExistingTree(node, ref thing); } if (node.action == TreeAction.Craft) { TechTypeExtensions.FromString(node.id, out TechType techType, false); root.AddCraftingNode(techType); } } }
private static void RemoveNodes(ref CraftNode nodes, List <Node> nodesToRemove, CraftTree.Type scheme) { // This method can be used to both remove single child nodes, thus removing one recipe from the tree. // Or it can remove entire tabs at once, removing the tab and all the recipes it contained in one go. foreach (Node nodeToRemove in nodesToRemove) { // Not for this fabricator. Skip. if (nodeToRemove.Scheme != scheme) { continue; } // Get the names of each node in the path to traverse tree until we reach the node we want. TreeNode currentNode = default; currentNode = nodes; // Travel the path down the tree. string currentPath = null; for (int step = 0; step < nodeToRemove.Path.Length; step++) { currentPath = nodeToRemove.Path[step]; if (step > nodeToRemove.Path.Length) { break; } currentNode = currentNode[currentPath]; } // Hold a reference to the parent node TreeNode parentNode = currentNode.parent; // Safty checks. if (currentNode != null && currentNode.id == currentPath) { currentNode.Clear(); // Remove all child nodes (if any) parentNode.RemoveNode(currentNode); // Remove the node } } }
private static void AddCustomTabs(ref CraftNode nodes, List <TabNode> customTabs, CraftTree.Type scheme) { foreach (TabNode tab in customTabs) { // Wrong crafter, skip. if (tab.Scheme != scheme) { continue; } TreeNode currentNode = default; currentNode = nodes; // Patch into game's CraftTree. for (int i = 0; i < tab.Path.Length; i++) { string currentPath = tab.Path[i]; Logger.Log("Tab Current Path: " + currentPath + " Tab: " + tab.Name + " Crafter: " + tab.Scheme.ToString(), LogLevel.Debug); TreeNode node = currentNode[currentPath]; // Reached the end of the line. if (node != null) { currentNode = node; } else { break; } } // Add the new tab node. var newNode = new CraftNode(tab.Name, TreeAction.Expand, TechType.None); currentNode.AddNode(new TreeNode[] { newNode }); } }
/// <summary> /// Removes the selected craft /// </summary> public static void RemoveSelectedCraft(CraftNode craftNode) { string craftPath = KSPPathHelper.GetAbsolutePath(craftNode.FilePath); ModNode node = ModSelectionTreeModel.SearchNodeByDestination(craftNode.FilePath, ModSelectionController.Model); DialogResult dlgResult = DialogResult.Cancel; if (node == null) { dlgResult = MessageBox.Show(View.ParentForm, Messages.MSG_CRAFT_NOT_FROM_MOD_DELETE_WARNING, string.Empty, MessageBoxButtons.YesNo, MessageBoxIcon.Warning); } if (node != null || dlgResult == DialogResult.Yes) { if (File.Exists(craftPath)) { File.Delete(craftPath); Messenger.AddInfo(string.Format(Messages.MSG_CRAFT_0_DELETED, craftPath)); if (node != null) { Messenger.AddInfo(string.Format(Messages.MSG_MODSELECTION_UPDATED_PART_0, node.Name)); node.Checked = false; node.NodeType = NodeType.UnknownFile; } model.Nodes.Remove(craftNode); foreach (CraftNode pNode in craftNode.Nodes) { if (pNode.RelatedPart != null) { pNode.RelatedPart.RemoveCraft(craftNode); Messenger.AddInfo(string.Format(Messages.MSG_PARTTAB_UPDATED_PART_0, pNode.RelatedPart.Name)); } } } } }
private static void PatchNodes(ref CraftNode nodes, List <CraftingNode> customNodes, CraftTree.Type scheme) { foreach (CraftingNode customNode in customNodes) { // Wrong crafter, just skip the node. if (customNode.Scheme != scheme) { continue; } // Have to do this to make sure C# shuts up. TreeNode node = default; node = nodes; // Loop through the path provided by the node. // Get the node for the last path. for (int i = 0; i < customNode.Path.Length; i++) { string currentPath = customNode.Path[i]; TreeNode currentNode = node[currentPath]; if (currentNode != null) { node = currentNode; } else { break; } } // Add the node. node.AddNode(new TreeNode[] { new CraftNode(customNode.TechType.AsString(false), TreeAction.Craft, customNode.TechType) }); } }
private static bool Prefix(CraftTree tree) { using (IEnumerator <CraftNode> enumerator = tree.nodes.Traverse(false)) { while (enumerator.MoveNext()) { CraftNode craftNode = enumerator.Current; if (craftNode.action == TreeAction.Craft) { TechType techType = craftNode.techType0; if (techType != TechType.None && !Core.RecipeBlacklist.Contains(techType.AsString())) { CraftTree.craftableTech.Add(techType); } else if (Core.RecipeBlacklist.Contains(techType.AsString())) { craftNode.techType0 = TechType.None; Core.Log($"TechType: {techType.AsString()} found in BlackList", true); } } } } return(false); }
private CraftTree CreateCraftingTree() { if (craftTree == null) { Dictionary <string, string> langLines = Language.main.strings; var atlasName = SpriteManager.mapping[SpriteManager.Group.Category]; #if SUBNAUTICA var group = Atlas.GetAtlas(atlasName).nameToSprite; #elif BELOWZERO var group = SpriteManager.atlases[atlasName]; #endif List <CraftNode> craftNodes = new List <CraftNode>(); CraftNode fab = CraftTree.FabricatorScheme(); CloneTabDetails(FabricatorScheme, fab, ref langLines, ref group); craftNodes.Add(fab); CraftNode wb = CraftTree.WorkbenchScheme(); CloneTabDetails(WorkBenchScheme, wb, ref langLines, ref group); craftNodes.Add(wb); CraftNode su = CraftTree.SeamothUpgradesScheme(); CloneTabDetails(SeamothUpgradesScheme, su, ref langLines, ref group); craftNodes.Add(su); CraftNode map = CraftTree.MapRoomSheme(); CloneTabDetails(MapRoomScheme, map, ref langLines, ref group); craftNodes.Add(map); #if SUBNAUTICA CraftNode cy = CraftTree.CyclopsFabricatorScheme(); CloneTabDetails(CyclopsFabScheme, cy, ref langLines, ref group); craftNodes.Add(cy); #elif BELOWZERO CraftNode st = CraftTree.SeaTruckFabricatorScheme(); CloneTabDetails(SeaTruckFabScheme, st, ref langLines, ref group); craftNodes.Add(st); #endif CraftNode aioRoot = new CraftNode("Root").AddNode(craftNodes.ToArray()); Type smlCTPatcher = typeof(CraftTreeHandler).Assembly.GetType("SMLHelper.V2.Patchers.CraftTreePatcher"); var customTrees = (Dictionary <CraftTree.Type, ModCraftTreeRoot>)smlCTPatcher.GetField("CustomTrees", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null); foreach (KeyValuePair <CraftTree.Type, ModCraftTreeRoot> entry in customTrees) { if (entry.Key == this.TreeTypeID) { continue; } CraftTree tree = entry.Value.CraftTreeCreation.Invoke(); CraftNode root = tree.nodes; string scheme = entry.Key.ToString(); CloneTabDetails(scheme, root, ref langLines, ref group); CloneTopLevelModTab(scheme, ref langLines, ref group); aioRoot.AddNode(root); } craftTree = new CraftTree(AioFabScheme, aioRoot); } return(craftTree); }
/// <summary> /// Opens the Craft Editor with the selected craft. /// </summary> public static void EditSelectedCraft(CraftNode craftNode) { MessageBox.Show("Not implemented yet!", string.Empty); }
private static void CyclopsFabricatorSchemePostfix(ref CraftNode __result) { PatchCraftTree(ref __result, CraftTree.Type.CyclopsFabricator); }
/// <summary> /// Creates crafts from the passed file. /// </summary> /// <param name="file">Full path to the craft file.</param> /// <returns>The crafts from the passed file.</returns> private static List <CraftNode> CreateCraftEntry(string file) { string adjustedPath = KSPPathHelper.GetAbsolutePath(file); var result = new List <CraftNode>(); if (string.IsNullOrEmpty(file) || !File.Exists(adjustedPath)) { return(result); } CraftNode craftNode = new CraftNode(); craftNode.Name = file; craftNode.FilePath = file; craftNode.Folder = GetCraftFolder(adjustedPath); result.Add(craftNode); bool partInfo = false; int bracetCount = 0; string[] lines = File.ReadLines(file).ToArray <string>(); foreach (string line in lines) { if (line == null) { Messenger.AddError(string.Format(Messages.MSG_ERROR_DURING_CRAFT_READING_0_UNEXPECTED_EMPTY_LINE, file)); continue; } string tempLine = line.Trim(); if (!partInfo) { if (tempLine.ToLower().StartsWith("ship =") || tempLine.ToLower().StartsWith("ship=")) { string name = tempLine.Split('=').Last(); craftNode.Text = name.Trim(); craftNode.Name = name.Trim(); } else if (tempLine.ToLower().StartsWith("type =") || tempLine.ToLower().StartsWith("type=")) { string type = tempLine.Split('=')[1]; craftNode.Type = type.Trim(); } else if (tempLine.ToLower().StartsWith("version =") || tempLine.ToLower().StartsWith("version=")) { string version = tempLine.Split('=')[1]; craftNode.Version = version.Trim(); } else if (tempLine.ToLower().StartsWith("part")) { partInfo = true; } } else { if (tempLine.StartsWith("{")) { ++bracetCount; } else if (tempLine.StartsWith("}")) { --bracetCount; if (bracetCount < 1) { partInfo = false; } } else if (tempLine.ToLower().StartsWith("part =") || tempLine.ToLower().StartsWith("part=")) { string partName = tempLine.Split('=')[1].Trim(); partName = partName.Substring(0, partName.LastIndexOf("_")); if (!craftNode.ContainsPart(partName)) { Messenger.AddInfo(string.Format(Messages.MSG_PART_0_ADDED_TO_CRAFT_1, partName, craftNode.Name)); craftNode.Nodes.Add(new CraftNode() { Name = partName + " (1)", FilePath = partName }); } else { try { CraftNode part = craftNode.GetPart(partName); int i1 = part.Name.LastIndexOf('(') + 1; if (i1 < 0) { continue; } int length = part.Name.Length - part.Name.LastIndexOf(')'); if (length < 0) { continue; } string str = part.Name.Substring(i1, length); int i = int.Parse(str) + 1; part.Name = string.Format("{0} ({1})", partName, i); Messenger.AddInfo(string.Format(Messages.MSG_PARTCOUNT_FOR_PART_0_IN_CRAFT_1_CHANGED_TO_2, partName, craftNode.Name, i)); } catch (Exception ex) { Messenger.AddError(string.Format(Messages.MSG_ERROR_DURING_CRAFT_READING_0, file), ex); } } } } } ////craftNode.SortPartsByDisplayText(); return(result); }
public static void ConstructorSchemePostfix(ref CraftNode __result) { AddCustomTabs(ref __result, customTabs, CraftScheme.Constructor); PatchNodes(ref __result, customNodes, CraftScheme.Constructor); }
private static void FabricatorSchemePostfix(ref CraftNode __result) { RemoveNodes(ref __result, NodesToRemove, CraftTree.Type.Fabricator); AddCustomTabs(ref __result, TabNodes, CraftTree.Type.Fabricator); PatchNodes(ref __result, CraftingNodes, CraftTree.Type.Fabricator); }
public static void WorkbenchSchemePostfix(ref CraftNode __result) { AddCustomTabs(ref __result, customTabs, CraftScheme.Workbench); PatchNodes(ref __result, customNodes, CraftScheme.Workbench); }
public static void SeamothUpgradesSchemePostfix(ref CraftNode __result) { AddCustomTabs(ref __result, customTabs, CraftScheme.SeamothUpgrades); PatchNodes(ref __result, customNodes, CraftScheme.SeamothUpgrades); }
private static void SeamothUpgradesSchemePostfix(ref CraftNode __result) { RemoveNodes(ref __result, NodesToRemove, CraftTree.Type.SeamothUpgrades); AddCustomTabs(ref __result, TabNodes, CraftTree.Type.SeamothUpgrades); PatchNodes(ref __result, CraftingNodes, CraftTree.Type.SeamothUpgrades); }
private static void WorkbenchSchemePostfix(ref CraftNode __result) { RemoveNodes(ref __result, NodesToRemove, CraftTree.Type.Workbench); AddCustomTabs(ref __result, TabNodes, CraftTree.Type.Workbench); PatchNodes(ref __result, CraftingNodes, CraftTree.Type.Workbench); }
public static void MapRoomShemePostfix(ref CraftNode __result) { AddCustomTabs(ref __result, customTabs, CraftScheme.MapRoom); PatchNodes(ref __result, customNodes, CraftScheme.MapRoom); }
private void CloneTabDetails(string scheme, CraftNode node, ref Dictionary <string, string> languageLines, ref Dictionary <string, Atlas.Sprite> group, ref Dictionary <string, Atlas.Sprite> atlas) { if (node == null) { return; } switch (node.action) { case TreeAction.Craft: return; case TreeAction.None: node.id = scheme; node.action = TreeAction.Expand; Console.WriteLine($"[AIOFabricator][INFO] Cloning tab nodes for '{scheme}:{node.id}'"); break; case TreeAction.Expand: { string clonedLangKey = string.Format(DisplayNameFormat, AioFabScheme, node.id); string origLangKey = string.Format(DisplayNameFormat, scheme, node.id); try { if (languageLines != null && !languageLines.ContainsKey(clonedLangKey) && languageLines.TryGetValue(origLangKey, out string origString)) { languageLines[clonedLangKey] = origString; } else { Console.WriteLine($"[AIOFabricator][WARN] Problem cloning language line for '{scheme}:{node.id}'{Environment.NewLine}Language resource not found"); } } catch (Exception ex) { Console.WriteLine($"[AIOFabricator][ERROR] Error cloning language line for '{scheme}:{node.id}'{Environment.NewLine}{ex.Message}"); } string origSpriteKey = string.Format(TabSpriteFormat, scheme, node.id); string clonedSpriteKey = string.Format(TabSpriteFormat, AioFabScheme, node.id); try { if (group != null && group.TryGetValue(origSpriteKey, out Atlas.Sprite groupSprite)) { group[clonedSpriteKey] = groupSprite; } else if (atlas != null && atlas.TryGetValue(origSpriteKey, out Atlas.Sprite resourceSprite)) { atlas[clonedSpriteKey] = resourceSprite; } else { Console.WriteLine($"[AIOFabricator][WARN] Problem cloning sprite for '{scheme}:{node.id}'{Environment.NewLine}Sprite resource not found"); } } catch (Exception ex) { Console.WriteLine($"[AIOFabricator][ERROR] Error cloning sprite for '{scheme}:{node.id}'{Environment.NewLine}{ex.Message}"); } break; } } foreach (CraftNode innerNode in node) { CloneTabDetails(scheme, innerNode, ref languageLines, ref group, ref atlas); } }
public static void CyclopsFabricatorSchemePostfix(ref CraftNode __result) { AddCustomTabs(ref __result, customTabs, CraftScheme.CyclopsFabricator); PatchNodes(ref __result, customNodes, CraftScheme.CyclopsFabricator); }