public ScenarioVehicle InsertVehicle(int consistIdx, int insertPos, AvailableVehicle vehicle) { XElement consist = ScenarioXml.Root.Descendants("cConsist").Skip(consistIdx).FirstOrDefault(); if (consist == null) { throw new Exception("Consist not found"); } XElement vehicles = consist.Element("RailVehicles"); bool atEnd = insertPos >= vehicles.Elements("cOwnedEntity").Count(); var insert = VehicleGenerator.GenerateVehicle( atEnd ? vehicles.Elements("cOwnedEntity").Last() : vehicles.Elements("cOwnedEntity").ElementAt(insertPos), vehicle); var elem = insert.Item1; elem.Attribute(XNamespace.Xmlns + "d").Remove(); if (atEnd) { vehicles.Add(elem); } else { vehicles.Elements("cOwnedEntity").ElementAt(insertPos).AddBeforeSelf(elem); } // Check InitialRV lists var cDriver = consist.Element("Driver").Element("cDriver"); if (cDriver != null) { var e = new XElement("e"); e.SetAttributeValue(Namespace + "type", "cDeltaString"); e.SetValue(insert.Item2.Number); var initialRV = cDriver.Element("InitialRV"); if (atEnd) { initialRV.Add(e); } else { var row = initialRV.Elements("e").ElementAt(insertPos); if (row != null) { row.AddBeforeSelf(e); } } } CreateBlueprintSetPreLoad(vehicle.Provider, vehicle.Product); return(insert.Item2); }
public static string GetVehicleDisplayName(Vehicle vehicle) { if (_vehicleDisplayNameTable.ContainsKey(vehicle.XmlPath)) { return(_vehicleDisplayNameTable[vehicle.XmlPath]); } Log.Debug("GetVehicleDisplayName: {0} is not in table, looking up..", vehicle.XmlPath); var binPath = Path.ChangeExtension(vehicle.XmlPath, "bin"); try { AvailableVehicle actualVehicle = new AvailableVehicle(binPath); _vehicleDisplayNameTable[vehicle.XmlPath] = actualVehicle.DisplayName; } catch (Exception) { _vehicleDisplayNameTable[vehicle.XmlPath] = vehicle.Name; } return(_vehicleDisplayNameTable[vehicle.XmlPath]); }
public static Tuple <XElement, ScenarioVehicle> GenerateVehicle(XElement prevElem, AvailableVehicle vehicle) { var retVehicle = new ScenarioVehicle(); retVehicle.CopyFrom(vehicle); XDocument doc; XmlNamespaceManager mgr = new XmlNamespaceManager(new NameTable()); mgr.AddNamespace("d", "http://www.kuju.com/TnT/2003/Delta"); XmlParserContext ctx = new XmlParserContext(null, mgr, null, XmlSpace.Default); using (XmlReader reader = XmlReader.Create(new StringReader(VehicleTemplates.GetXml(vehicle.Type)), null, ctx)) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(reader); doc = XDocument.Parse(xmlDoc.OuterXml); } var cOwnedEntity = doc.Root; XElement typeSpecificElement; switch (vehicle.Type) { case VehicleType.Engine: typeSpecificElement = cOwnedEntity.Element("Component").Element("cEngine"); break; case VehicleType.Wagon: typeSpecificElement = cOwnedEntity.Element("Component").Element("cWagon"); break; case VehicleType.Tender: typeSpecificElement = cOwnedEntity.Element("Component").Element("cTender"); break; default: throw new Exception("Unknown vehicle type!"); } typeSpecificElement.Element("UniqueNumber").SetValue(retVehicle.Number); var followers = typeSpecificElement.Element("Followers"); var prevFollowers = prevElem.Element("Component").Descendants("Followers").First().Elements("Network-cTrackFollower"); foreach (var cTrackFollower in prevFollowers) { var newFollower = new XElement(cTrackFollower); followers.Add(newFollower); } XElement cEntityContainer = cOwnedEntity .Element("Component").Element("cEntityContainer").Element("StaticChildrenMatrix"); for (var i = 0; i < vehicle.EntityCount; i++) { var newNode = Utilities.GenerateEntityContainerItem(); cEntityContainer.Add(newNode); } XElement cCargoComponent = cOwnedEntity .Element("Component").Element("cCargoComponent").Element("InitialLevel"); for (var i = 0; i < vehicle.CargoCount; i++) { var newNode = Utilities.GenerateCargoComponentItem( vehicle.CargoComponents[i].Item1, vehicle.CargoComponents[i].Item2); cCargoComponent.Add(newNode); } var cPosOri = new XElement(prevElem.Element("Component").Element("cPosOri")); cOwnedEntity.Element("Component").Add(cPosOri); cOwnedEntity.Element("Name").SetValue(vehicle.Name); var idElements = cOwnedEntity .DescendantsAndSelf() .Where(elem => elem.Attribute(Namespace + "id") != null); Random idRandom = new Random(); foreach (var elem in idElements) { var id = idRandom.Next(100000000, 999999999); elem.SetAttributeValue(Namespace + "id", id); } var entityId = cOwnedEntity.Element("EntityID"); entityId.Add(Utilities.GenerateCGUID()); XElement cAbsoluteBlueprintID = cOwnedEntity .Element("BlueprintID").Element("iBlueprintLibrary-cAbsoluteBlueprintID"); cAbsoluteBlueprintID .Element("BlueprintSetID").Element("iBlueprintLibrary-cBlueprintSetID").Element("Provider") .SetValue(vehicle.Provider); cAbsoluteBlueprintID .Element("BlueprintSetID").Element("iBlueprintLibrary-cBlueprintSetID").Element("Product") .SetValue(vehicle.Product); cAbsoluteBlueprintID.Element("BlueprintID").SetValue(vehicle.BlueprintId); if (vehicle.IsReskin) { cAbsoluteBlueprintID = cOwnedEntity .Element("ReskinBlueprintID").Element("iBlueprintLibrary-cAbsoluteBlueprintID"); cAbsoluteBlueprintID .Element("BlueprintSetID").Element("iBlueprintLibrary-cBlueprintSetID").Element("Provider") .SetValue(vehicle.ReskinProvider); cAbsoluteBlueprintID .Element("BlueprintSetID").Element("iBlueprintLibrary-cBlueprintSetID").Element("Product") .SetValue(vehicle.ReskinProduct); cAbsoluteBlueprintID.Element("BlueprintID").SetValue(vehicle.ReskinBlueprintId); } return(new Tuple <XElement, ScenarioVehicle>(cOwnedEntity, retVehicle)); }
public void ReplaceVehicle(int consistIdx, int vehicleIdx, AvailableVehicle newVehicle) { // Locate the consist and vehicle XElement consist = ScenarioXml.Root.Descendants("cConsist").Skip(consistIdx).FirstOrDefault(); if (consist == null) { throw new Exception("Consist not found"); } XElement vehicle = consist.Element("RailVehicles").Descendants("cOwnedEntity").Skip(vehicleIdx).FirstOrDefault(); if (vehicle == null) { throw new Exception("Vehicle not found"); } // Update blueprint ID in Scenario.bin XElement blueprintID = vehicle.Element("BlueprintID").Element("iBlueprintLibrary-cAbsoluteBlueprintID"); var origBlueprintID = blueprintID.Element("BlueprintID").Value; blueprintID.Element("BlueprintSetID").Element("iBlueprintLibrary-cBlueprintSetID").Element("Provider").SetValue(newVehicle.Provider); blueprintID.Element("BlueprintSetID").Element("iBlueprintLibrary-cBlueprintSetID").Element("Product").SetValue(newVehicle.Product); blueprintID.Element("BlueprintID").SetValue(newVehicle.BlueprintId); vehicle.Element("Name").SetValue(newVehicle.Name); // Update reskin info XElement reskinBlueprintID = vehicle.Element("ReskinBlueprintID").Element("iBlueprintLibrary-cAbsoluteBlueprintID"); if (newVehicle.IsReskin) { Log.Debug("ReplaceVehicle: Reskin set to {0}", newVehicle.ReskinXmlPath); reskinBlueprintID.Element("BlueprintSetID").Element("iBlueprintLibrary-cBlueprintSetID").Element("Provider").SetValue(newVehicle.ReskinProvider); reskinBlueprintID.Element("BlueprintSetID").Element("iBlueprintLibrary-cBlueprintSetID").Element("Product").SetValue(newVehicle.ReskinProduct); reskinBlueprintID.Element("BlueprintID").SetValue(newVehicle.ReskinBlueprintId); } else { // Remove reskin info Log.Debug("ReplaceVehicle: Remove reskin info"); reskinBlueprintID.Element("BlueprintSetID").Element("iBlueprintLibrary-cBlueprintSetID").Element("Provider").SetValue(""); reskinBlueprintID.Element("BlueprintSetID").Element("iBlueprintLibrary-cBlueprintSetID").Element("Product").SetValue(""); reskinBlueprintID.Element("BlueprintID").SetValue(""); } // Update engine and wagon dependent parameters XElement cElement = vehicle.Descendants().Where(element => element.Name == "cWagon" || element.Name == "cEngine" || element.Name == "cTender").FirstOrDefault(); if (cElement == null) { throw new Exception("Cannot find cWagon or cEngine element!"); } if (cElement.Name == "cEngine" && newVehicle.Type != VehicleType.Engine) { // We should remove additional nodes for engines cElement.Elements() .Where(element => element.Name == "DisabledEngine" || element.Name == "AWSTimer" || element.Name == "AWSExpired" || element.Name == "TPWSDistance") .Remove(); vehicle.Element("Component").Element("cEngineSimContainer").Remove(); } if (cElement.Name == "cTender" && newVehicle.Type != VehicleType.Tender) { // We should remove additional nodes for tenders cElement.Elements() .Where(element => element.Name == "CoalLevel" || element.Name == "WaterLevel") .Remove(); } if (newVehicle.Type == VehicleType.Wagon) { cElement.Name = "cWagon"; } else if (newVehicle.Type == VehicleType.Engine && cElement.Name != "cEngine") { // We should create additional nodes for engines cElement.Name = "cEngine"; Log.Debug("Creating additional nodes for replacement {0}", newVehicle.DisplayName); XElement disabledEngine = new XElement("DisabledEngine"); disabledEngine.SetAttributeValue(Namespace + "type", "bool"); disabledEngine.SetValue("0"); XElement awsTimer = new XElement("AWSTimer"); awsTimer.SetAttributeValue(Namespace + "type", "sFloat32"); awsTimer.SetAttributeValue(Namespace + "alt_encoding", "0000000000000000"); awsTimer.SetAttributeValue(Namespace + "precision", "string"); awsTimer.SetValue("0"); XElement awsExpired = new XElement("AWSExpired"); awsExpired.SetAttributeValue(Namespace + "type", "bool"); awsExpired.SetValue("0"); XElement tpwsDistance = new XElement("TPWSDistance"); tpwsDistance.SetAttributeValue(Namespace + "type", "sFloat32"); tpwsDistance.SetAttributeValue(Namespace + "alt_encoding", "0000000000000000"); tpwsDistance.SetAttributeValue(Namespace + "precision", "string"); tpwsDistance.SetValue("0"); cElement.Add(disabledEngine, awsTimer, awsExpired, tpwsDistance); Random idRandom = new Random(); int id; do { id = idRandom.Next(100000000, 999999999); } while (ScenarioXml.Descendants().Where(elem => (elem.Attribute(Namespace + "id") != null && elem.Attribute(Namespace + "id").Value == id.ToString())).Any()); XElement cEngineSimContainer = new XElement("cEngineSimContainer"); cEngineSimContainer.SetAttributeValue(Namespace + "id", id.ToString()); vehicle.Element("Component").Add(cEngineSimContainer); } else if (newVehicle.Type == VehicleType.Tender && cElement.Name != "cTender") { cElement.Name = "cTender"; Log.Debug("Creating additional tender nodes for replacement {0}", newVehicle.DisplayName); XElement coalLevel = new XElement("CoalLevel"); coalLevel.SetAttributeValue(Namespace + "type", "sFloat32"); coalLevel.SetAttributeValue(Namespace + "alt_encoding", "0000000000000000"); coalLevel.SetAttributeValue(Namespace + "precision", "string"); coalLevel.SetValue("0"); XElement waterLevel = new XElement("WaterLevel"); waterLevel.SetAttributeValue(Namespace + "type", "sFloat32"); waterLevel.SetAttributeValue(Namespace + "alt_encoding", "0000000000000000"); waterLevel.SetAttributeValue(Namespace + "precision", "string"); waterLevel.SetValue("0"); cElement.Add(coalLevel, waterLevel); } // Cargo component count matching XElement cCargoComponent = vehicle.Element("Component").Element("cCargoComponent").Element("InitialLevel"); int cargoCount = cCargoComponent.Elements().Count(); if (newVehicle.CargoCount > cargoCount) { Log.Debug("Need to create cargo initial level holders {0} -> {1}", cargoCount, newVehicle.CargoCount); for (int i = cargoCount; i < newVehicle.CargoCount; ++i) { XElement newNode = new XElement("e"); newNode.SetAttributeValue(Namespace + "type", "sFloat32"); newNode.SetAttributeValue(Namespace + "alt_encoding", "0000000000000000"); newNode.SetAttributeValue(Namespace + "precision", "string"); newNode.SetValue("0"); cCargoComponent.Add(newNode); } } else if (newVehicle.CargoCount < cargoCount) { Log.Debug("Need to remove cargo initial level holders {0} -> {1}", cargoCount, newVehicle.CargoCount); cCargoComponent.Elements().Take(cargoCount - newVehicle.CargoCount).Remove(); } // Entity container count matching XElement cEntityContainer = vehicle.Element("Component").Element("cEntityContainer").Element("StaticChildrenMatrix"); int entityCount = cEntityContainer.Elements().Count(); if (newVehicle.EntityCount > entityCount) { Log.Debug("Need to add entities {0} -> {1}", entityCount, newVehicle.EntityCount); for (int i = entityCount; i < newVehicle.EntityCount; ++i) { XElement newNode = new XElement("e"); newNode.SetAttributeValue(Namespace + "numElements", "16"); newNode.SetAttributeValue(Namespace + "elementType", "sFloat32"); newNode.SetAttributeValue(Namespace + "precision", "string"); newNode.SetValue("1.0000000 0.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 0.0000000 1.0000000"); cEntityContainer.Add(newNode); } } else if (newVehicle.EntityCount < entityCount) { Log.Debug("Need to remove entities {0} -> {1}", entityCount, newVehicle.EntityCount); cEntityContainer.Elements().Take(entityCount - newVehicle.EntityCount).Remove(); } // If the consist is driven by the player, loco name in ScenarioProperties.xml should be updated if (consist.Element("Driver").Element("cDriver") != null) { XElement cDriver = consist.Element("Driver").Element("cDriver"); if (cDriver.Element("PlayerDriver") != null) { if (cDriver.Element("PlayerDriver").Value == "1") { Log.Debug("Train is driven by player; checking whether the loco is swapped"); var key = cDriver.Element("ServiceName").Descendants("Key").First().Value; XElement sDriverFrontEndDetails = ScenarioProperties.Root.Element("FrontEndDriverList") .Elements("sDriverFrontEndDetails").Where(element => element.Element("ServiceName").Element("Localisation-cUserLocalisedString").Element("Key").Value == key).FirstOrDefault(); if (sDriverFrontEndDetails == null) { Log.Debug("Could not find sDriverFrontEndDetails with key {0}!", key); } else { var consistLocoBlueprintId = sDriverFrontEndDetails.Element("LocoBP").Descendants("BlueprintID").First().Value; if (consistLocoBlueprintId == origBlueprintID) { Log.Debug("Update new sDriverFrontEndDetails to Blueprint ID {0}", newVehicle.BlueprintId); XElement destLocalisedString = sDriverFrontEndDetails.Element("LocoName").Element("Localisation-cUserLocalisedString"); XElement origLocalisedString = newVehicle.NameLocalisedString; Utilities.CopyUserLocalisedString(destLocalisedString, origLocalisedString); sDriverFrontEndDetails.Element("LocoBP").Descendants("Provider").First().Value = newVehicle.Provider; sDriverFrontEndDetails.Element("LocoBP").Descendants("Product").First().Value = newVehicle.Product; sDriverFrontEndDetails.Element("LocoBP").Descendants("BlueprintID").First().Value = newVehicle.BlueprintId; sDriverFrontEndDetails.Element("LocoAuthor").Value = newVehicle.Provider; string newVehicleXmlPath = newVehicle.XmlPath; sDriverFrontEndDetails.Element("FilePath").Value = newVehicleXmlPath.Substring(0, newVehicleXmlPath.LastIndexOf('\\')); } } } } } CreateBlueprintSetPreLoad(newVehicle.Provider, newVehicle.Product); if (newVehicle.IsReskin) { CreateBlueprintSetPreLoad(newVehicle.ReskinProvider, newVehicle.ReskinProduct); } }