private void ThisObjectInGameDataViewToolStripMenuItem_Click(object sender, EventArgs e) { if (treeView1.SelectedNode == null) { throw new NullReferenceException("SelectedNode was null."); } else { Type t = treeView1.SelectedNode.GetType(); if (t.Equals(typeof(SolarSystem_TN))) { SolarSystem_TN node = (SolarSystem_TN)treeView1.SelectedNode; treeView1.SelectedNode = node.LinkedGameDataNode; // Trigger refresh HellionExplorerProgram.RefreshSelectedOjectPathBarText(treeView1.SelectedNode); HellionExplorerProgram.RefreshListView(treeView1.SelectedNode); HellionExplorerProgram.RefreshSelectedObjectSummaryText(treeView1.SelectedNode); HellionExplorerProgram.RefreshStatusStrip(treeView1.SelectedNode); } else { throw new InvalidOperationException("Unexpected node type " + t.ToString()); } } }
/// <summary> /// Re-arranges (rehydrates) existing ship nodes by their DockedToShipGUID forming a tree where the /// root node is the parent vessel of the docked ships (and is what shows up on radar in-game). /// </summary> /// <remarks> /// Although this particular function is non-recursive, recursive calls are made when calling /// the HETreeNode.GetAllNodes() to get sub-nodes. /// </remarks> public void RehydrateDockedShips() { IEnumerable <SolarSystem_TN> shipsToBeReparented = RootNode.GetChildNodes(includeSubtrees: true) .Cast <SolarSystem_TN>() .Where(p => (p.NodeType == Base_TN_NodeType.Ship) && (p.DockedToShipGUID > 0)); foreach (SolarSystem_TN node in shipsToBeReparented) { // If this node has a non-zero value for DockedToShipGUID, process it. if (node.DockedToShipGUID != 0) { // Find the node that has the GUID matching the DockedToShipGUID of this node. // There can be only one! SolarSystem_TN newParentNode = RootNode.GetChildNodes(includeSubtrees: true) .Cast <SolarSystem_TN>() .Where(p => p.GUID == node.DockedToShipGUID) .Single(); // If the .Single() causes an exception, there's not exactly one module docked to that port! // Remove the ship to be re-parented from it's current parent's node collection. node.Parent.Nodes.Remove(node); // Add the ship being re-parented to the new parent's node collection. newParentNode.Nodes.Insert(0, node); } else { throw new InvalidOperationException(); } } }
private void RootOfDockingTreeToolStripMenuItem_Click(object sender, EventArgs e) { // This is only applicable in the Solar System View SolarSystem_TN node = (SolarSystem_TN)treeView1.SelectedNode; treeView1.SelectedNode = node.DockingTreeRoot; // Trigger refresh HellionExplorerProgram.RefreshSelectedOjectPathBarText(treeView1.SelectedNode); HellionExplorerProgram.RefreshListView(treeView1.SelectedNode); HellionExplorerProgram.RefreshSelectedObjectSummaryText(treeView1.SelectedNode); HellionExplorerProgram.RefreshStatusStrip(treeView1.SelectedNode); }
/// <summary> /// Constructor that takes an GameData object and uses this as it's data source. /// </summary> /// <param name="gameData"></param> public SolarSystem(GameData gameData) { RootNode = new SolarSystem_TN(passedOwner: this, nodeName: "Solar System", nodeType: Base_TN_NodeType.SolarSystemView) //, "Solar System") { // Hellion, the star, has a ParentGUID of -1, so we utilise this to attach it to // the Solar System root node by giving that a GUID of -1 (and no parentGUID). GUID = -1, ParentGUID = -100 }; if (gameData == null) { throw new NullReferenceException("gameData was null."); } else { // Store a reference to the GameData object GameData = gameData; // Create Solar System hierarchical structure from the Celestial Bodies RebuildSolarSystem(); } }
private void TreeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { // Update the object path + name + Tag in the object identifier bar HellionExplorerProgram.RefreshSelectedOjectPathBarText(e.Node); HellionExplorerProgram.RefreshListView(e.Node); HellionExplorerProgram.RefreshSelectedObjectSummaryText(e.Node); HellionExplorerProgram.RefreshStatusStrip(e.Node); // Show menu only if the right mouse button is clicked. if (e.Button == MouseButtons.Right) { Base_TN node = (Base_TN)e.Node; // Get the node that the user has clicked. if (node == null) { return; } // Select in the TreeView the node the user has clicked. treeView1.SelectedNode = node; // Determine node type and activate appropriate jump to menu items. Type t = node.GetType(); // Handles Json_TN nodes for the Game Data representation. if (t.Equals(typeof(Json_TN))) { // We're working with a GAME DATA node // Enable the Json Data View //jsonDataViewToolStripMenuItem.Enabled = true; // Editing of Json is now handled by the Edit menu item on the // context menu. At this point only Objects seem // suitable for use in the Json editor - otherwise de-serialisation // fails and changes can't be applied to the main document. switch (node.NodeType) { case Base_TN_NodeType.SaveFile: case Base_TN_NodeType.DataFile: case Base_TN_NodeType.StationBlueprintFile: case Base_TN_NodeType.JsonObject: //case Base_TN_NodeType.JsonArray: // Show the Edit menu item. editToolStripMenuItem1.Enabled = true; break; default: // Disable the Edit menu item. editToolStripMenuItem1.Enabled = false; break; } // Enable the Jump to sub-menu jumpToToolStripMenuItem.Enabled = true; // GD nodes always have load items visible, even if enabled loadNextLevelToolStripMenuItem.Enabled = true; loadAllLevelsToolStripMenuItem.Enabled = true; // We're in the Game Data already, so disable selection of it thisObjectInGameDataViewToolStripMenuItem.Enabled = false; thisObjectInGameDataViewToolStripMenuItem.Checked = true; // Disable these two as they're Solar System related rootOfDockingTreeToolStripMenuItem.Enabled = false; parentCelestialBodyToolStripMenuItem.Enabled = false; // Cast the node to an Json_TN type Json_TN gDnode = (Json_TN)treeView1.SelectedNode; // Disable the LoadNextLevel item if it's already been loaded. if (gDnode.ChildNodesLoaded) { loadNextLevelToolStripMenuItem.Enabled = false; } else { loadNextLevelToolStripMenuItem.Enabled = true; } if (gDnode.LinkedSolarSystemNode != null) { // It's a Game Data node that has a linked Solar System node // Enable the Jump to menu item thisObjectInSolarSystemViewToolStripMenuItem.Enabled = true; thisObjectInSolarSystemViewToolStripMenuItem.Checked = false; } else { thisObjectInSolarSystemViewToolStripMenuItem.Enabled = false; thisObjectInSolarSystemViewToolStripMenuItem.Checked = false; } } else if (t.Equals(typeof(Base_TN)) && node.NodeType == Base_TN_NodeType.StationBlueprintFile) { // Enable the Edit menu item. editToolStripMenuItem1.Enabled = true; // Disable the Jump to sub-menu jumpToToolStripMenuItem.Enabled = false; // Disable Jump to sub-items. thisObjectInGameDataViewToolStripMenuItem.Enabled = false; thisObjectInGameDataViewToolStripMenuItem.Checked = false; thisObjectInSolarSystemViewToolStripMenuItem.Enabled = false; thisObjectInSolarSystemViewToolStripMenuItem.Checked = false; rootOfDockingTreeToolStripMenuItem.Enabled = false; parentCelestialBodyToolStripMenuItem.Enabled = false; // Disable load items. loadNextLevelToolStripMenuItem.Enabled = false; loadAllLevelsToolStripMenuItem.Enabled = false; } // Handles SolarSystem_TN Nodes for the Solar System representation. else if (t.Equals(typeof(SolarSystem_TN))) { // We're working with a SOLAR SYSTEM node // Hide the Edit menu item. editToolStripMenuItem1.Enabled = false; // Disable the Json Data View option. //jsonDataViewToolStripMenuItem.Enabled = false; // Solar System nodes never have load options loadNextLevelToolStripMenuItem.Enabled = false; loadAllLevelsToolStripMenuItem.Enabled = false; // We're in the Solar System already, so disable selection of it thisObjectInSolarSystemViewToolStripMenuItem.Enabled = false; thisObjectInSolarSystemViewToolStripMenuItem.Checked = true; // Cast the node as an SolarSystem_TN type SolarSystem_TN sSnode = (SolarSystem_TN)treeView1.SelectedNode; if (sSnode.GUID == -1 || sSnode.NodeType == Base_TN_NodeType.SolarSystemView || sSnode.NodeType == Base_TN_NodeType.BlueprintHierarchyView) { // We're dealing with the Solar System Root Node or a Blueprint Hierarchy // View node, special cases. jumpToToolStripMenuItem.Enabled = false; thisObjectInGameDataViewToolStripMenuItem.Enabled = false; thisObjectInGameDataViewToolStripMenuItem.Checked = false; } else { if (sSnode.LinkedGameDataNode == null) // throw new NullReferenceException("sNode.LinkedGameDataNode was null."); { thisObjectInGameDataViewToolStripMenuItem.Enabled = false; thisObjectInGameDataViewToolStripMenuItem.Checked = false; } else { thisObjectInGameDataViewToolStripMenuItem.Enabled = true; thisObjectInGameDataViewToolStripMenuItem.Checked = false; } // Enable the Jump to sub-menu unless it's the Solar System root node if (sSnode.GUID != -1) { jumpToToolStripMenuItem.Enabled = true; } else { jumpToToolStripMenuItem.Enabled = false; } // Enable the Root of Docking Tree option only if the node's parent type // is a ship, indicating it is docked to something (rather than something // being docked *to* this node i.e. child nodes). rootOfDockingTreeToolStripMenuItem.Enabled = sSnode.IsDockedToParent; } } // Handles Blueprint_TN for blueprint files. else if (t.Equals(typeof(Blueprint_TN))) { // Some decision making logic needed here if (node.NodeType == Base_TN_NodeType.StationBlueprintFile) { // Show the Edit menu item. editToolStripMenuItem1.Enabled = true; } else { editToolStripMenuItem1.Enabled = false; } // Disable the Json Data View //jsonDataViewToolStripMenuItem.Enabled = false; // Disable the Jump to sub-menu jumpToToolStripMenuItem.Enabled = false; // Disable the Solar System Jump to option thisObjectInSolarSystemViewToolStripMenuItem.Enabled = false; thisObjectInSolarSystemViewToolStripMenuItem.Checked = false; // Disable the Game Data Jump to option thisObjectInGameDataViewToolStripMenuItem.Enabled = false; thisObjectInGameDataViewToolStripMenuItem.Checked = false; // Disable these two as they're Solar System related rootOfDockingTreeToolStripMenuItem.Enabled = false; parentCelestialBodyToolStripMenuItem.Enabled = false; // Disable the load options loadNextLevelToolStripMenuItem.Enabled = false; loadAllLevelsToolStripMenuItem.Enabled = false; } // Default behaviour - handles other node types. else { // Hide the Edit menu item. editToolStripMenuItem1.Enabled = false; // Disable the Json Data View //jsonDataViewToolStripMenuItem.Enabled = false; // Disable the Jump to sub-menu jumpToToolStripMenuItem.Enabled = false; // Disable the Solar System Jump to option thisObjectInSolarSystemViewToolStripMenuItem.Enabled = false; thisObjectInSolarSystemViewToolStripMenuItem.Checked = false; // Disable the Game Data Jump to option thisObjectInGameDataViewToolStripMenuItem.Enabled = false; thisObjectInGameDataViewToolStripMenuItem.Checked = false; // Disable these two as they're Solar System related rootOfDockingTreeToolStripMenuItem.Enabled = false; parentCelestialBodyToolStripMenuItem.Enabled = false; // Disable the load options loadNextLevelToolStripMenuItem.Enabled = false; loadAllLevelsToolStripMenuItem.Enabled = false; } // Show the ContextMenuStrip. contextMenuStrip1.Show(treeView1, e.Location); } }
/// <summary> /// Rehydrates (rebuilds) the node hierarchy based on GUID and ParentGUID. /// </summary> public bool RehydrateGUIDHierarchy() { SolarSystem_TN currentParentNode = null; bool errorState = false; foreach (SolarSystem_TN node in RootNode.GetChildNodes(includeSubtrees: true)) { Debug.WriteLine(">>>Rehydrating " + node.Name + ">>" + node.Text); // If this node has a non-zero value for DockedToShipGUID, process it. if (node.ParentGUID == -100) { // There should be only one case where the node processed has a value of zero that is valid and // that's the Solar System node, which has no parent node - it's parent is the TreeViewControl. if (node.GUID != -1) { throw new InvalidOperationException(node.Text + " - Node's parent GUID is zero."); } } else { // Find the single node that has the GUID matching the DockedToShipGUID of this node. // There can be only one! IEnumerable <SolarSystem_TN> newParentNodes = RootNode.GetChildNodes(includeSubtrees: true) .Cast <SolarSystem_TN>() .Where(p => p.GUID == node.ParentGUID); //.Single(); if (newParentNodes.Count() != 1) { Debug.WriteLine("newParentNodes.count=" + newParentNodes.Count()); } try { SolarSystem_TN newParentNode = newParentNodes.Single(); // Cast the node.Parent to an SolarSystem_TN (so we can access ClearCachedData) currentParentNode = (SolarSystem_TN)node.Parent; // Remove the ship to be re-parented from it's current parent's node collection. // The null case is the Solar System RootNode that's parent is the TreeView control not a node. if (currentParentNode != null) { currentParentNode.Nodes.Remove(node); } // Add the ship being re-parented to the new parent's node collection. newParentNode.Nodes.Insert(0, node); } catch (InvalidOperationException ex) { // If the .Single() causes an exception, there's more than one module docked to that port (!), // or the GUID that it's docked to can't be found :( StringBuilder sb = new StringBuilder(); sb.Append("RehydrateGUIDHierarchy threw an InvalidOperationException." + Environment.NewLine); sb.Append("newParentNodes.Count() " + newParentNodes.Count() + Environment.NewLine); sb.Append(Environment.NewLine); sb.Append("Exception Details" + Environment.NewLine); sb.Append(ex); //throw new Exception(sb.ToString()); } } } return(errorState); }
/// <summary> /// Adds Solar System nodes of the specified type to the RootNode, generated from the /// Game Data nodes. /// </summary> /// <param name="nodeType"></param> public void AddSolarSystemObjectsByType(Base_TN_NodeType nodeType) { switch (nodeType) { case Base_TN_NodeType.Star: case Base_TN_NodeType.Planet: case Base_TN_NodeType.Moon: // These come from the Static Data - handled by the CelestialBodies.json member of the DataDictionary if (!GameData.StaticData.DataDictionary.TryGetValue("CelestialBodies.json", out Json_File_UI celestialBodiesJsonBaseFile)) { throw new InvalidOperationException ("AddSolarSystemObjectsByType: Unable to access the CelestialBodies.json from the Static Data Dictionary."); } else { // We're expecting the Array or Object nodes as the parent token. if (celestialBodiesJsonBaseFile.RootNode.Nodes.Count != 1) { throw new InvalidOperationException ("AddSolarSystemObjectsByType: celestialBodiesJsonBaseFile.RootNode.Nodes.Count != 1"); } foreach (Json_TN node in celestialBodiesJsonBaseFile.RootNode.FirstNode.Nodes) { Base_TN_NodeType newNodeType = Base_TN_NodeType.Unknown; JObject obj = (JObject)node.JData; if (obj == null) { throw new NullReferenceException ("Adding CelestialBodies - obj was null."); } // If the node doesn't have a parent guid set it to -1000. long newNodeParentGUID = obj["ParentGUID"] != null ? (long)obj["ParentGUID"] : -1000L; switch (newNodeParentGUID) { case 0: case -1000: throw new InvalidOperationException ("AddSolarSystemObjectsByType: Failed to read ParentGUID for node " + node.Name); case -1: // It's the star, Hellion. newNodeType = Base_TN_NodeType.Star; break; case 1: // It's a planet, orbiting the star. newNodeType = Base_TN_NodeType.Planet; break; default: // It's a moon, not a space station! newNodeType = Base_TN_NodeType.Moon; break; } SolarSystem_TN newNode = node.CreateLinkedSolarSystemNode(newNodeType); RootNode.Nodes.Insert(0, newNode); } } break; case Base_TN_NodeType.Asteroid: case Base_TN_NodeType.Ship: case Base_TN_NodeType.Player: // Set up the find key that's used to locate the TreeNode representing // the Ships, Asteroids and Players collections in the .save file. string findKey = string.Empty; switch (nodeType) { case Base_TN_NodeType.Asteroid: findKey = "Asteroids"; break; case Base_TN_NodeType.Ship: findKey = "Ships"; break; case Base_TN_NodeType.Player: findKey = "Players"; break; } if (findKey == string.Empty) { throw new InvalidOperationException ("AddSolarSystemObjectsByType: findKey was empty."); } TreeNode[] tmpMatches = GameData.SaveFile.RootNode.FirstNode.Nodes.Find(findKey, searchAllChildren: false); Json_TN sectionRootNode = null; if (tmpMatches.Count() > 0) { // Grab the first match - there shouldn't be more then one anyway. sectionRootNode = (Json_TN)tmpMatches?[0]; } else { Debug.Print("AddSolarSystemObjectsByType({0}) - sectionRootNode was null.", nodeType); } // The nodes of interest are children of the node representing the JArray. Json_TN arrayRootNode = null; if (sectionRootNode?.Nodes.Count > 0) { arrayRootNode = (Json_TN)sectionRootNode?.Nodes[0]; foreach (Json_TN node in arrayRootNode.Nodes) { Debug.Print("Node Name: " + node.Name); JObject obj = (JObject)node.JData; long newNodeParentGUID; if (nodeType == Base_TN_NodeType.Player) { newNodeParentGUID = (long)obj["ParentGUID"]; } else { newNodeParentGUID = (long)obj["OrbitData"]["ParentGUID"]; } long?newNodeGUID = (long?)obj["GUID"]; Debug.Print("ParentGUID: " + newNodeParentGUID); Debug.Print("GUID: " + newNodeGUID); SolarSystem_TN newNode = node.CreateLinkedSolarSystemNode(nodeType); if (nodeType == Base_TN_NodeType.Player) { if (newNodeParentGUID == newNodeGUID) { // Player is ALIVE and in space newNode.ParentGUID = -1; // Needs to be greater than zero to place players below the star node. newNode.OrbitData.SemiMajorAxis = 1; } else { // Player is dead, display below alive players. newNode.OrbitData.SemiMajorAxis = 10; } } RootNode.Nodes.Insert(0, newNode); } } else { Debug.Print("AddSolarSystemObjectsByType({0}) - subRootNode was null.", nodeType); } break; } }