public override bool Load(ConfigNode configNode) { // Load base class bool valid = base.Load(configNode); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "basename", x => basename = x, this); int index = 0; foreach (ConfigNode child in ConfigNodeUtil.GetChildNodes(configNode, "CONDITION")) { DataNode childDataNode = new DataNode("CONDITION_" + index++, dataNode, this); try { ConfigNodeUtil.SetCurrentDataNode(childDataNode); OpenBase.ConditionDetail cd = new OpenBase.ConditionDetail(); valid &= ConfigNodeUtil.ParseValue<OpenBase.ConditionDetail.Condition>(child, "condition", x => cd.condition = x, this); valid &= ConfigNodeUtil.ParseValue<string>(child, "parameter", x => cd.parameter = x, this, "", x => ValidateMandatoryParameter(x, cd.condition)); conditions.Add(cd); } finally { ConfigNodeUtil.SetCurrentDataNode(dataNode); } } valid &= ConfigNodeUtil.ValidateMandatoryChild(configNode, "CONDITION", this); return valid; }
public DataNode(string name, DataNode parent, IContractConfiguratorFactory factory) { if (parent != null) { // Check for duplicate name - probably could be more efficient here string origName = name; int i = 1; while (parent.children.Any(dn => dn.name == name)) { name = origName + "_" + i++; } } this.parent = parent; this.factory = factory; this.name = name; if (parent != null) { parent.children.Add(this); root = parent.root; } else { root = this; } }
public DataNode(string name, DataNode parent, IContractConfiguratorFactory factory) { this.parent = parent; this.factory = factory; this.name = name; if (parent != null && parent.factory.GetType() != typeof(ContractGroup)) { // Check for duplicate name - probably could be more efficient here int i = 1; while (parent.children.Any(dn => dn.name == this.name)) { this.name = name + "_" + i++; } parent.children.Add(this); root = parent.root; } else if (factory != null && factory.GetType() != typeof(ContractGroup)) { root = this; } else { root = null; } }
public static Expression Parse(ConfigNode configNode, DataNode dataNode, ExpressionFactory factory) { Expression e = new Expression(dataNode); e.factory = factory; e.Load(configNode); e.factory = null; return e; }
/// <summary> /// Copy constructor. /// </summary> /// <param name="source"></param> public Expression(Expression source) { dataNode = source.dataNode; onOfferExpr = new List<ExpVal>(source.onOfferExpr); onAcceptExpr = new List<ExpVal>(source.onAcceptExpr); onSuccessExpr = new List<ExpVal>(source.onSuccessExpr); onFailExpr = new List<ExpVal>(source.onFailExpr); onParameterComplete = new Dictionary<string, List<ExpVal>>(source.onParameterComplete); SetupMap(); }
public override bool Load(ConfigNode configNode) { // Load base class bool valid = base.Load(configNode); valid &= ConfigNodeUtil.ParseValue<TriggeredBehaviour.State>(configNode, "onState", x => onState = x, this, TriggeredBehaviour.State.CONTRACT_SUCCESS); if (onState == TriggeredBehaviour.State.PARAMETER_COMPLETED || onState == TriggeredBehaviour.State.PARAMETER_FAILED) { valid &= ConfigNodeUtil.ParseValue<List<string>>(configNode, "parameter", x => parameter = x, this); } kerbalInfo = new List<ChangeKerbalType.KerbalInfo>(); int index = 0; foreach (ConfigNode child in ConfigNodeUtil.GetChildNodes(configNode, "KERBAL_INFO")) { string kerbInfoNode = "KERBAL_INFO" + index++; DataNode childDataNode = new DataNode(kerbInfoNode, dataNode, this); try { ConfigNodeUtil.SetCurrentDataNode(childDataNode); ChangeKerbalType.KerbalInfo kerb = new ChangeKerbalType.KerbalInfo(); kerbalInfo.Add(kerb); valid &= ConfigNodeUtil.ParseValue<Kerbal>(child, "kerbal", x => kerb.kerbal = x, this); valid &= ConfigNodeUtil.ParseValue<ProtoCrewMember.KerbalType?>(child, "kerbalType", x => kerb.kerbalType = x, this, (ProtoCrewMember.KerbalType?)null); valid &= ConfigNodeUtil.ParseValue<string>(child, "trait", x => kerb.trait = x, this, ""); } finally { ConfigNodeUtil.SetCurrentDataNode(dataNode); } } valid &= ConfigNodeUtil.ValidateMandatoryChild(configNode, "KERBAL_INFO", this); return valid; }
/// <summary> /// Loads the contract type details from the given config node. /// </summary> /// <param name="configNode">The config node to load from.</param> /// <returns>Whether the load was successful.</returns> public bool Load(ConfigNode configNode) { LoggingUtil.LogLevel origLogLevel = LoggingUtil.logLevel; try { // Logging on LoggingUtil.CaptureLog = true; ConfigNodeUtil.SetCurrentDataNode(null); // Load values that are immediately required bool valid = true; valid &= ConfigNodeUtil.ParseValue<ContractGroup>(configNode, "group", x => group = x, this, (ContractGroup)null); // Set up the data node dataNode = new DataNode(configNode.GetValue("name"), group != null ? group.dataNode : null, this); ConfigNodeUtil.SetCurrentDataNode(dataNode); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "name", x => name = x, this); // Try to turn on trace mode valid &= ConfigNodeUtil.ParseValue<bool>(configNode, "trace", x => trace = x, this, false); if (trace) { LoggingUtil.logLevel = LoggingUtil.LogLevel.VERBOSE; LoggingUtil.LogWarning(this, "Tracing enabled for contract type " + name); } // Load contract text details valid &= ConfigNodeUtil.ParseValue<string>(configNode, "title", x => title = x, this); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "tag", x => tag = x, this, ""); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "description", x => description = x, this, (string)null); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "topic", x => topic = x, this, ""); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "subject", x => subject = x, this, ""); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "motivation", x => motivation = x, this, ""); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "notes", x => notes = x, this, (string)null); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "synopsis", x => synopsis = x, this); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "completedMessage", x => completedMessage = x, this); // Load optional attributes valid &= ConfigNodeUtil.ParseValue<Agent>(configNode, "agent", x => agent = x, this, (Agent)null); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "minExpiry", x => minExpiry = x, this, 1.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "maxExpiry", x => maxExpiry = x, this, 7.0f, x => Validation.GE(x, minExpiry)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "deadline", x => deadline = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<bool>(configNode, "cancellable", x => cancellable = x, this, true); valid &= ConfigNodeUtil.ParseValue<bool>(configNode, "declinable", x => declinable = x, this, true); valid &= ConfigNodeUtil.ParseValue<bool>(configNode, "autoAccept", x => autoAccept = x, this, false); valid &= ConfigNodeUtil.ParseValue<List<Contract.ContractPrestige>>(configNode, "prestige", x => prestige = x, this, new List<Contract.ContractPrestige>()); valid &= ConfigNodeUtil.ParseValue<CelestialBody>(configNode, "targetBody", x => targetBody = x, this, (CelestialBody)null); valid &= ConfigNodeUtil.ParseValue<int>(configNode, "maxCompletions", x => maxCompletions = x, this, 0, x => Validation.GE(x, 0)); valid &= ConfigNodeUtil.ParseValue<int>(configNode, "maxSimultaneous", x => maxSimultaneous = x, this, 0, x => Validation.GE(x, 0)); // Load rewards valid &= ConfigNodeUtil.ParseValue<float>(configNode, "rewardFunds", x => rewardFunds = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "rewardReputation", x => rewardReputation = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "rewardScience", x => rewardScience = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "failureFunds", x => failureFunds = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "failureReputation", x => failureReputation = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "advanceFunds", x => advanceFunds = x, this, 0.0f, x => Validation.GE(x, 0.0f)); // Load other values valid &= ConfigNodeUtil.ParseValue<double>(configNode, "weight", x => weight = x, this, 1.0, x => Validation.GE(x, 0.0f)); // Merge in data from the parent contract group for (ContractGroup currentGroup = group; currentGroup != null; currentGroup = currentGroup.parent) { // Merge dataValues - this is a flag saying what values need to be unique at the contract level foreach (KeyValuePair<string, bool> pair in currentGroup.dataValues) { dataValues[group.name + ":" + pair.Key] = pair.Value; } // Merge uniquenessChecks foreach (KeyValuePair<string, DataNode.UniquenessCheck> pair in currentGroup.uniquenessChecks) { uniquenessChecks[group.name + ":" + pair.Key] = pair.Value; } } // Load DATA nodes valid &= dataNode.ParseDataNodes(configNode, this, dataValues, uniquenessChecks); // Check for unexpected values - always do this last valid &= ConfigNodeUtil.ValidateUnexpectedValues(configNode, this); log = LoggingUtil.capturedLog; LoggingUtil.CaptureLog = false; // Load parameters foreach (ConfigNode contractParameter in ConfigNodeUtil.GetChildNodes(configNode, "PARAMETER")) { ParameterFactory paramFactory = null; valid &= ParameterFactory.GenerateParameterFactory(contractParameter, this, out paramFactory); if (paramFactory != null) { paramFactories.Add(paramFactory); if (paramFactory.hasWarnings) { hasWarnings = true; } } } // Load behaviours foreach (ConfigNode requirementNode in ConfigNodeUtil.GetChildNodes(configNode, "BEHAVIOUR")) { BehaviourFactory behaviourFactory = null; valid &= BehaviourFactory.GenerateBehaviourFactory(requirementNode, this, out behaviourFactory); if (behaviourFactory != null) { behaviourFactories.Add(behaviourFactory); if (behaviourFactory.hasWarnings) { hasWarnings = true; } } } // Load requirements foreach (ConfigNode requirementNode in ConfigNodeUtil.GetChildNodes(configNode, "REQUIREMENT")) { ContractRequirement requirement = null; valid &= ContractRequirement.GenerateRequirement(requirementNode, this, out requirement); if (requirement != null) { requirements.Add(requirement); if (requirement.hasWarnings) { hasWarnings = true; } } } // Logging on LoggingUtil.CaptureLog = true; // Check we have at least one valid parameter if (paramFactories.Count() == 0) { LoggingUtil.LogError(this.GetType(), ErrorPrefix() + ": Need at least one parameter for a contract!"); valid = false; } // Do the deferred loads valid &= ConfigNodeUtil.ExecuteDeferredLoads(); config = configNode.ToString(); hash = config.GetHashCode(); enabled = valid; log += LoggingUtil.capturedLog; if (LoggingUtil.logLevel == LoggingUtil.LogLevel.VERBOSE || LoggingUtil.logLevel == LoggingUtil.LogLevel.DEBUG) { //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // to write the complete config and log for contract to both the system log and // a seperate CC log file // string pattern = @"\[(VERBOSE|DEBUG|INFO|WARNING|ERROR)\] ContractConfigurator\.ExpressionParser.BaseParser.+\n"; string replacement = ""; Regex rgx = new Regex(pattern); // First, write to the standard log file. the regex strips out the leading text of the line, but // if you want the text there, then just remove the rgx.Replace LoggingUtil.LogDebug(this, config); // Write the log out, ignoring the BaseParser lines LoggingUtil.LogDebug(this, rgx.Replace(log, replacement)); // Now write to the CC log file, in a much cleaner manner string path = ccLogFile; // Delete the file first time through, ignore any errors if (deleteCCLogfile) { deleteCCLogfile = false; try { if (File.Exists(path)) File.Delete(path); } catch { LoggingUtil.LogError(this, "Exception while attempting to delete the file: " + path); } } // Create the file if it doesn't exist if (!File.Exists(path)) { // Create a file to write to. try { using (StreamWriter sw = File.CreateText(path)) {} } catch { LoggingUtil.LogError(this, "Exception while attempting to create the file: " + path); } } // This regex also strips out the second part of the line, so that the output is very clean string pattern2 = @"\[(VERBOSE|DEBUG|INFO|WARNING|ERROR)\] ContractConfigurator\.ExpressionParser\.DataNode: "; Regex rgx2 = new Regex(pattern2); // Now write the config and the cleaned up log to it try { using (StreamWriter sw = File.AppendText (path)) { sw.WriteLine (config); sw.WriteLine("++++++++++\n"); sw.WriteLine(rgx2.Replace(rgx.Replace(log, replacement), replacement)); sw.WriteLine("=================================================================================="); } } catch { LoggingUtil.LogError(this, "Exception while attempting to write to the file: " + path); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ } LoggingUtil.CaptureLog = false; return valid; } catch { enabled = false; throw; } finally { LoggingUtil.logLevel = origLogLevel; loaded = true; } }
public static WaypointGenerator Create(ConfigNode configNode, WaypointGeneratorFactory factory) { WaypointGenerator wpGenerator = new WaypointGenerator(); bool valid = true; int index = 0; foreach (ConfigNode child in ConfigNodeUtil.GetChildNodes(configNode)) { DataNode dataNode = new DataNode("WAYPOINT_" + index, factory.dataNode, factory); try { ConfigNodeUtil.SetCurrentDataNode(dataNode); dataNode["type"] = child.name; double? altitude = null; WaypointData wpData = new WaypointData(child.name); // Use an expression to default - then it'll work for dynamic contracts if (!child.HasValue("targetBody")) { child.AddValue("targetBody", "@/targetBody"); } valid &= ConfigNodeUtil.ParseValue<CelestialBody>(child, "targetBody", x => wpData.waypoint.celestialName = x != null ? x.name : "", factory); valid &= ConfigNodeUtil.ParseValue<List<string>>(child, "name", x => wpData.names = x, factory, new List<string>()); valid &= ConfigNodeUtil.ParseValue<double?>(child, "altitude", x => altitude = x, factory, (double?)null); valid &= ConfigNodeUtil.ParseValue<List<string>>(child, "parameter", x => wpData.parameter = x, factory, new List<string>()); valid &= ConfigNodeUtil.ParseValue<bool>(child, "hidden", x => wpData.waypoint.visible = !x, factory, false); if (!wpData.waypoint.visible) { valid &= ConfigNodeUtil.ParseValue<string>(child, "icon", x => wpData.waypoint.id = x, factory, ""); } else { valid &= ConfigNodeUtil.ParseValue<string>(child, "icon", x => wpData.waypoint.id = x, factory); } valid &= ConfigNodeUtil.ParseValue<bool>(child, "underwater", x => wpData.underwater = x, factory, false); valid &= ConfigNodeUtil.ParseValue<bool>(child, "clustered", x => wpData.waypoint.isClustered = x, factory, false); // Track the index wpData.waypoint.index = index++; // Get altitude if (altitude == null) { wpData.waypoint.altitude = 0.0; wpData.randomAltitude = true; } else { wpData.waypoint.altitude = altitude.Value; } // Get settings that differ by type if (child.name == "WAYPOINT") { valid &= ConfigNodeUtil.ParseValue<double>(child, "latitude", x => wpData.waypoint.latitude = x, factory); valid &= ConfigNodeUtil.ParseValue<double>(child, "longitude", x => wpData.waypoint.longitude = x, factory); } else if (child.name == "RANDOM_WAYPOINT") { // Get settings for randomization valid &= ConfigNodeUtil.ParseValue<bool>(child, "waterAllowed", x => wpData.waterAllowed = x, factory, true); valid &= ConfigNodeUtil.ParseValue<bool>(child, "forceEquatorial", x => wpData.forceEquatorial = x, factory, false); valid &= ConfigNodeUtil.ParseValue<int>(child, "count", x => wpData.count = x, factory, 1, x => Validation.GE(x, 1)); } else if (child.name == "RANDOM_WAYPOINT_NEAR") { // Get settings for randomization valid &= ConfigNodeUtil.ParseValue<bool>(child, "waterAllowed", x => wpData.waterAllowed = x, factory, true); // Get near waypoint details valid &= ConfigNodeUtil.ParseValue<int>(child, "nearIndex", x => wpData.nearIndex = x, factory, x => Validation.GE(x, 0) && Validation.LT(x, wpGenerator.waypoints.Count)); valid &= ConfigNodeUtil.ParseValue<bool>(child, "chained", x => wpData.chained = x, factory, false); valid &= ConfigNodeUtil.ParseValue<int>(child, "count", x => wpData.count = x, factory, 1, x => Validation.GE(x, 1)); // Get distances valid &= ConfigNodeUtil.ParseValue<double>(child, "minDistance", x => wpData.minDistance = x, factory, 0.0, x => Validation.GE(x, 0.0)); valid &= ConfigNodeUtil.ParseValue<double>(child, "maxDistance", x => wpData.maxDistance = x, factory, x => Validation.GT(x, 0.0)); } else if (child.name == "PQS_CITY") { wpData.randomAltitude = false; string dummy = null; valid &= ConfigNodeUtil.ParseValue<string>(child, "pqsCity", x => dummy = x, factory, x => { bool v = true; if (!string.IsNullOrEmpty(wpData.waypoint.celestialName)) { try { CelestialBody body = FlightGlobals.Bodies.Where(b => b.name == wpData.waypoint.celestialName).First(); wpData.pqsCity = body.GetComponentsInChildren<PQSCity>(true).Where(pqs => pqs.name == x).First(); } catch (Exception e) { LoggingUtil.LogError(typeof(WaypointGenerator), "Couldn't load PQSCity with name '" + x + "'"); LoggingUtil.LogException(e); v = false; } } else { // Force this to get re-run when the targetBody is loaded throw new DataNode.ValueNotInitialized("/targetBody"); } return v; }); valid &= ConfigNodeUtil.ParseValue<Vector3d>(child, "pqsOffset", x => wpData.pqsOffset = x, factory, new Vector3d()); } else { LoggingUtil.LogError(factory, "Unrecognized waypoint node: '" + child.name + "'"); valid = false; } // Check for unexpected values valid &= ConfigNodeUtil.ValidateUnexpectedValues(child, factory); // Copy waypoint data WaypointData old = wpData; for (int i = 0; i < old.count; i++) { wpData = new WaypointData(old, null); wpGenerator.waypoints.Add(wpData); if (old.parameter.Any()) { wpData.parameter = new List<string>(); wpData.parameter.Add(old.parameter.Count() == 1 ? old.parameter.First() : old.parameter.ElementAtOrDefault(i)); } // Set the name if (old.names.Any()) { wpData.waypoint.name = (old.names.Count() == 1 ? old.names.First() : old.names.ElementAtOrDefault(i)); } if (string.IsNullOrEmpty(wpData.waypoint.name) || wpData.waypoint.name.ToLower() == "site") { wpData.waypoint.name = StringUtilities.GenerateSiteName(random.Next(), wpData.waypoint.celestialBody, !wpData.waterAllowed); } // Handle waypoint chaining if (wpData.chained && i != 0) { wpData.nearIndex = wpGenerator.waypoints.Count - 2; } } } finally { ConfigNodeUtil.SetCurrentDataNode(factory.dataNode); } } return valid ? wpGenerator : null; }
/// <summary> /// Loads the contract group details from the given config node. /// </summary> /// <param name="configNode">The config node to load from</param> /// <returns>Whether we were successful.</returns> public bool Load(ConfigNode configNode) { try { dataNode = new DataNode(configNode.GetValue("name"), this); LoggingUtil.CaptureLog = true; ConfigNodeUtil.SetCurrentDataNode(dataNode); bool valid = true; valid &= ConfigNodeUtil.ParseValue<string>(configNode, "name", x => name = x, this); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "displayName", x => displayName = x, this, name); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "minVersion", x => minVersion = x, this, ""); valid &= ConfigNodeUtil.ParseValue<int>(configNode, "maxCompletions", x => maxCompletions = x, this, 0, x => Validation.GE(x, 0)); valid &= ConfigNodeUtil.ParseValue<int>(configNode, "maxSimultaneous", x => maxSimultaneous = x, this, 0, x => Validation.GE(x, 0)); valid &= ConfigNodeUtil.ParseValue<List<string>>(configNode, "disabledContractType", x => disabledContractType = x, this, new List<string>()); if (!string.IsNullOrEmpty(minVersion)) { if (Util.Version.VerifyAssemblyVersion("ContractConfigurator", minVersion) == null) { valid = false; var ainfoV = Attribute.GetCustomAttribute(typeof(ExceptionLogWindow).Assembly, typeof(AssemblyInformationalVersionAttribute)) as AssemblyInformationalVersionAttribute; string title = "Contract Configurator " + ainfoV.InformationalVersion + " Message"; string message = "The contract group '" + name + "' requires at least Contract Configurator " + minVersion + " to work, and you are running version " + ainfoV.InformationalVersion + ". Please upgrade Contract Configurator to use the contracts in this group."; DialogOption dialogOption = new DialogOption("Okay", new Callback(DoNothing), true); PopupDialog.SpawnPopupDialog(new MultiOptionDialog(message, title, HighLogic.Skin, dialogOption), false, HighLogic.Skin); } } // Load DATA nodes valid &= dataNode.ParseDataNodes(configNode, this, dataValues, uniquenessChecks); // Do the deferred loads valid &= ConfigNodeUtil.ExecuteDeferredLoads(); config = configNode.ToString(); log += LoggingUtil.capturedLog; LoggingUtil.CaptureLog = false; // Load child groups foreach (ConfigNode childNode in ConfigNodeUtil.GetChildNodes(configNode, "CONTRACT_GROUP")) { ContractGroup child = null; string childName = childNode.GetValue("name"); try { child = new ContractGroup(childName); } catch (ArgumentException) { LoggingUtil.LogError(this, "Couldn't load CONTRACT_GROUP '" + childName + "' due to a duplicate name."); valid = false; continue; } valid &= child.Load(childNode); child.parent = this; child.dataNode.Parent = dataNode; if (child.hasWarnings) { hasWarnings = true; } } // Check for unexpected values - always do this last valid &= ConfigNodeUtil.ValidateUnexpectedValues(configNode, this); // Invalidate children if (!valid) { Invalidate(); } enabled = valid; return valid; } catch { enabled = false; throw; } }
public Expression(DataNode dataNode) { this.dataNode = dataNode; SetupMap(); }
public Type GetType(string key) { DataNode node = NodeForKey(ref key); return(node.data.ContainsKey(key) && node.data[key] != null ? node.data[key].type : null); }
/// <summary> /// Validates whether the given value is initialized or not. /// </summary> /// <param name="key">The key to check for</param> /// <returns>True if the value has been read</returns> public bool IsInitialized(string key) { DataNode node = NodeForKey(ref key); return(node.data.ContainsKey(key) && node.data[key] != null && node.data[key].initialized); }
public abstract object ParseExpressionGeneric(string key, string expression, DataNode dataNode);
public abstract void ExecuteAndStoreExpression(string key, string expression, DataNode dataNode);
public static SpawnVessel Create(ConfigNode configNode, SpawnVesselFactory factory) { SpawnVessel spawnVessel = new SpawnVessel(); ConfigNodeUtil.ParseValue<bool>(configNode, "deferVesselCreation", x => spawnVessel.deferVesselCreation = x, factory, false); bool valid = true; int index = 0; foreach (ConfigNode child in ConfigNodeUtil.GetChildNodes(configNode, "VESSEL")) { DataNode dataNode = new DataNode("VESSEL_" + index++, factory.dataNode, factory); try { ConfigNodeUtil.SetCurrentDataNode(dataNode); VesselData vessel = new VesselData(); // Get name if (child.HasValue("name")) { valid &= ConfigNodeUtil.ParseValue<string>(child, "name", x => vessel.name = x, factory); } // Get craft details if (child.HasValue("craftURL")) { valid &= ConfigNodeUtil.ParseValue<string>(child, "craftURL", x => vessel.craftURL = x, factory); } if (child.HasValue("craftPart")) { valid &= ConfigNodeUtil.ParseValue<AvailablePart>(child, "craftPart", x => vessel.craftPart = x, factory); } valid &= ConfigNodeUtil.AtLeastOne(child, new string[] { "craftURL", "craftPart" }, factory); valid &= ConfigNodeUtil.ParseValue<string>(child, "flagURL", x => vessel.flagURL = x, factory, (string)null); valid &= ConfigNodeUtil.ParseValue<VesselType>(child, "vesselType", x => vessel.vesselType = x, factory, VesselType.Ship); // Use an expression to default - then it'll work for dynamic contracts if (!child.HasValue("targetBody")) { child.AddValue("targetBody", "@/targetBody"); } valid &= ConfigNodeUtil.ParseValue<CelestialBody>(child, "targetBody", x => vessel.body = x, factory); // Get landed stuff if (child.HasValue("pqsCity")) { string pqsCityStr = null; valid &= ConfigNodeUtil.ParseValue<string>(child, "pqsCity", x => pqsCityStr = x, factory); if (pqsCityStr != null) { try { vessel.pqsCity = vessel.body.GetComponentsInChildren<PQSCity>(true).Where(pqs => pqs.name == pqsCityStr).First(); } catch (Exception e) { LoggingUtil.LogError(typeof(WaypointGenerator), "Couldn't load PQSCity with name '" + pqsCityStr + "'"); LoggingUtil.LogException(e); valid = false; } } valid &= ConfigNodeUtil.ParseValue<Vector3d>(child, "pqsOffset", x => vessel.pqsOffset = x, factory, new Vector3d()); // Don't expect these to load anything, but do it to mark as initialized valid &= ConfigNodeUtil.ParseValue<double>(child, "lat", x => vessel.latitude = x, factory, 0.0); valid &= ConfigNodeUtil.ParseValue<double>(child, "lon", x => vessel.longitude = x, factory, 0.0); // Do load alt and height valid &= ConfigNodeUtil.ParseValue<double?>(child, "alt", x => vessel.altitude = x, factory, (double?)null); valid &= ConfigNodeUtil.ParseValue<float>(child, "height", x => vessel.height = x, factory, !string.IsNullOrEmpty(vessel.craftURL) ? 0.0f : 2.5f); vessel.orbiting = false; // Generate PQS city coordinates LoggingUtil.LogVerbose(factory, "Generating coordinates from PQS city for Vessel " + vessel.name); // Translate by the PQS offset (inverse transform of coordinate system) Vector3d position = vessel.pqsCity.transform.position; Vector3d v = vessel.pqsOffset; Vector3d i = vessel.pqsCity.transform.right; Vector3d j = vessel.pqsCity.transform.forward; Vector3d k = vessel.pqsCity.transform.up; Vector3d offsetPos = new Vector3d( (j.y * k.z - j.z * k.y) * v.x + (i.z * k.y - i.y * k.z) * v.y + (i.y * j.z - i.z * j.y) * v.z, (j.z * k.x - j.x * k.z) * v.x + (i.x * k.z - i.z * k.x) * v.y + (i.z * j.x - i.x * j.z) * v.z, (j.x * k.y - j.y * k.x) * v.x + (i.y * k.x - i.x * k.y) * v.y + (i.x * j.y - i.y * j.x) * v.z ); offsetPos *= (i.x * j.y * k.z) + (i.y * j.z * k.x) + (i.z * j.x * k.y) - (i.z * j.y * k.x) - (i.y * j.x * k.z) - (i.x * j.z * k.y); vessel.latitude = vessel.body.GetLatitude(position + offsetPos); vessel.longitude = vessel.body.GetLongitude(position + offsetPos); } else if (child.HasValue("lat") && child.HasValue("lon")) { valid &= ConfigNodeUtil.ParseValue<double>(child, "lat", x => vessel.latitude = x, factory); valid &= ConfigNodeUtil.ParseValue<double>(child, "lon", x => vessel.longitude = x, factory); valid &= ConfigNodeUtil.ParseValue<double?>(child, "alt", x => vessel.altitude = x, factory, (double?)null); valid &= ConfigNodeUtil.ParseValue<float>(child, "height", x => vessel.height = x, factory, !string.IsNullOrEmpty(vessel.craftURL) ? 0.0f : 2.5f); vessel.orbiting = false; } // Get orbit else { valid &= ConfigNodeUtil.ParseValue<Orbit>(child, "ORBIT", x => vessel.orbit = x, factory); vessel.orbiting = true; } valid &= ConfigNodeUtil.ParseValue<float>(child, "heading", x => vessel.heading = x, factory, 0.0f); valid &= ConfigNodeUtil.ParseValue<float>(child, "pitch", x => vessel.pitch = x, factory, 0.0f); valid &= ConfigNodeUtil.ParseValue<float>(child, "roll", x => vessel.roll = x, factory, 0.0f); // Get additional flags valid &= ConfigNodeUtil.ParseValue<bool>(child, "owned", x => vessel.owned = x, factory, false); // Handle the CREW nodes foreach (ConfigNode crewNode in ConfigNodeUtil.GetChildNodes(child, "CREW")) { int count = 1; valid &= ConfigNodeUtil.ParseValue<int>(crewNode, "count", x => count = x, factory, 1); for (int i = 0; i < count; i++) { CrewData cd = new CrewData(); // Read crew details valid &= ConfigNodeUtil.ParseValue<string>(crewNode, "name", x => cd.name = x, factory, (string)null); valid &= ConfigNodeUtil.ParseValue<bool>(crewNode, "addToRoster", x => cd.addToRoster = x, factory, true); // Check for unexpected values valid &= ConfigNodeUtil.ValidateUnexpectedValues(crewNode, factory); // Add the record vessel.crew.Add(cd); } } // Check for unexpected values valid &= ConfigNodeUtil.ValidateUnexpectedValues(child, factory); // Add to the list spawnVessel.vessels.Add(vessel); } finally { ConfigNodeUtil.SetCurrentDataNode(factory.dataNode); } } if (!configNode.HasNode("VESSEL")) { valid = false; LoggingUtil.LogError(factory, "SpawnVessel requires at least one VESSEL node."); } return valid ? spawnVessel : null; }
public static SpawnVessel Create(ConfigNode configNode, SpawnVesselFactory factory) { SpawnVessel spawnVessel = new SpawnVessel(); ConfigNodeUtil.ParseValue<bool>(configNode, "deferVesselCreation", x => spawnVessel.deferVesselCreation = x, factory, false); bool valid = true; int index = 0; foreach (ConfigNode child in ConfigNodeUtil.GetChildNodes(configNode, "VESSEL")) { DataNode dataNode = new DataNode("VESSEL_" + index++, factory.dataNode, factory); try { ConfigNodeUtil.SetCurrentDataNode(dataNode); VesselData vessel = new VesselData(); // Get name if (child.HasValue("name")) { valid &= ConfigNodeUtil.ParseValue<string>(child, "name", x => vessel.name = x, factory); } // Get craft details if (child.HasValue("craftURL")) { valid &= ConfigNodeUtil.ParseValue<string>(child, "craftURL", x => vessel.craftURL = x, factory); } if (child.HasValue("craftPart")) { valid &= ConfigNodeUtil.ParseValue<AvailablePart>(child, "craftPart", x => vessel.craftPart = x, factory); } valid &= ConfigNodeUtil.AtLeastOne(child, new string[] { "craftURL", "craftPart" }, factory); valid &= ConfigNodeUtil.ParseValue<string>(child, "flagURL", x => vessel.flagURL = x, factory, (string)null); valid &= ConfigNodeUtil.ParseValue<VesselType>(child, "vesselType", x => vessel.vesselType = x, factory, VesselType.Ship); // Use an expression to default - then it'll work for dynamic contracts if (!child.HasValue("targetBody")) { child.AddValue("targetBody", "@/targetBody"); } valid &= ConfigNodeUtil.ParseValue<CelestialBody>(child, "targetBody", x => vessel.body = x, factory); // Get landed stuff if (child.HasValue("lat") && child.HasValue("lon")) { valid &= ConfigNodeUtil.ParseValue<double>(child, "lat", x => vessel.latitude = x, factory); valid &= ConfigNodeUtil.ParseValue<double>(child, "lon", x => vessel.longitude = x, factory); valid &= ConfigNodeUtil.ParseValue<double?>(child, "alt", x => vessel.altitude = x, factory, (double?)null); valid &= ConfigNodeUtil.ParseValue<float>(child, "height", x => vessel.height = x, factory, !string.IsNullOrEmpty(vessel.craftURL) ? 0.0f : 2.5f); vessel.orbiting = false; } // Get orbit else { valid &= ConfigNodeUtil.ParseValue<Orbit>(child, "ORBIT", x => vessel.orbit = x, factory); vessel.orbiting = true; } valid &= ConfigNodeUtil.ParseValue<float>(child, "heading", x => vessel.heading = x, factory, 0.0f); valid &= ConfigNodeUtil.ParseValue<float>(child, "pitch", x => vessel.pitch = x, factory, 0.0f); valid &= ConfigNodeUtil.ParseValue<float>(child, "roll", x => vessel.roll = x, factory, 0.0f); // Get additional flags valid &= ConfigNodeUtil.ParseValue<bool>(child, "owned", x => vessel.owned = x, factory, false); // Handle the CREW nodes foreach (ConfigNode crewNode in ConfigNodeUtil.GetChildNodes(child, "CREW")) { int count = 1; valid &= ConfigNodeUtil.ParseValue<int>(crewNode, "count", x => count = x, factory, 1); for (int i = 0; i < count; i++) { CrewData cd = new CrewData(); // Read crew details valid &= ConfigNodeUtil.ParseValue<string>(crewNode, "name", x => cd.name = x, factory, (string)null); valid &= ConfigNodeUtil.ParseValue<bool>(crewNode, "addToRoster", x => cd.addToRoster = x, factory, true); // Check for unexpected values valid &= ConfigNodeUtil.ValidateUnexpectedValues(crewNode, factory); // Add the record vessel.crew.Add(cd); } } // Check for unexpected values valid &= ConfigNodeUtil.ValidateUnexpectedValues(child, factory); // Add to the list spawnVessel.vessels.Add(vessel); } finally { ConfigNodeUtil.SetCurrentDataNode(factory.dataNode); } } if (!configNode.HasNode("VESSEL")) { valid = false; LoggingUtil.LogError(factory, "SpawnVessel requires at least one VESSEL node."); } return valid ? spawnVessel : null; }
/// <summary> /// Loads the contract group details from the given config node. /// </summary> /// <param name="configNode">The config node to load from</param> /// <returns>Whether we were successful.</returns> public bool Load(ConfigNode configNode) { try { dataNode = new DataNode(configNode.GetValue("name"), this); LoggingUtil.CaptureLog = true; ConfigNodeUtil.SetCurrentDataNode(dataNode); bool valid = true; string unused; valid &= ConfigNodeUtil.ParseValue<string>(configNode, "name", x => name = x, this); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "displayName", x => displayName = x, this, name); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "minVersion", x => minVersionStr = x, this, ""); valid &= ConfigNodeUtil.ParseValue<int>(configNode, "maxCompletions", x => maxCompletions = x, this, 0, x => Validation.GE(x, 0)); valid &= ConfigNodeUtil.ParseValue<int>(configNode, "maxSimultaneous", x => maxSimultaneous = x, this, 0, x => Validation.GE(x, 0)); valid &= ConfigNodeUtil.ParseValue<List<string>>(configNode, "disabledContractType", x => disabledContractType = x, this, new List<string>()); valid &= ConfigNodeUtil.ParseValue<Agent>(configNode, "agent", x => agent = x, this, (Agent)null); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "sortKey", x => sortKey = x, this, displayName); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "tip", x => unused = x, this, ""); if (configNode.HasValue("sortKey") && parent == null) { sortKey = displayName; LoggingUtil.LogWarning(this, ErrorPrefix() + ": Using the sortKey field is only applicable on child CONTRACT_GROUP elements"); } if (!string.IsNullOrEmpty(minVersionStr)) { if (Util.Version.VerifyAssemblyVersion("ContractConfigurator", minVersionStr) == null) { valid = false; var ainfoV = Attribute.GetCustomAttribute(typeof(ExceptionLogWindow).Assembly, typeof(AssemblyInformationalVersionAttribute)) as AssemblyInformationalVersionAttribute; string title = "Contract Configurator " + ainfoV.InformationalVersion + " Message"; string message = "The contract group '" + name + "' requires at least Contract Configurator " + minVersionStr + " to work, and you are running version " + ainfoV.InformationalVersion + ". Please upgrade Contract Configurator to use the contracts in this group."; DialogGUIButton dialogOption = new DialogGUIButton("Okay", new Callback(DoNothing), true); PopupDialog.SpawnPopupDialog(new MultiOptionDialog(message, title, UISkinManager.GetSkin("default"), dialogOption), false, UISkinManager.GetSkin("default")); } } // Load DATA nodes valid &= dataNode.ParseDataNodes(configNode, this, dataValues, uniquenessChecks); // Do the deferred loads valid &= ConfigNodeUtil.ExecuteDeferredLoads(); // Do post-deferred load warnings if (agent == null) { LoggingUtil.LogWarning(this, ErrorPrefix() + ": Providing the agent field for all CONTRACT_GROUP nodes is highly recommended, as the agent is used to group contracts in Mission Control."); } if (string.IsNullOrEmpty(minVersionStr) || minVersion < ContractConfigurator.ENHANCED_UI_VERSION) { LoggingUtil.LogWarning(this, ErrorPrefix() + ": No minVersion or older minVersion provided. It is recommended that the minVersion is set to at least 1.15.0 to turn important warnings for deprecated functionality into errors."); } if (!configNode.HasValue("displayName")) { LoggingUtil.LogWarning(this, ErrorPrefix() + ": No display name provided. A display name is recommended, as it is used in the Mission Control UI."); } config = configNode.ToString(); log += LoggingUtil.capturedLog; LoggingUtil.CaptureLog = false; // Load child groups foreach (ConfigNode childNode in ConfigNodeUtil.GetChildNodes(configNode, "CONTRACT_GROUP")) { ContractGroup child = null; string childName = childNode.GetValue("name"); try { child = new ContractGroup(childName); } catch (ArgumentException) { LoggingUtil.LogError(this, "Couldn't load CONTRACT_GROUP '" + childName + "' due to a duplicate name."); valid = false; continue; } child.parent = this; valid &= child.Load(childNode); child.dataNode.Parent = dataNode; if (child.hasWarnings) { hasWarnings = true; } } // Check for unexpected values - always do this last valid &= ConfigNodeUtil.ValidateUnexpectedValues(configNode, this); // Invalidate children if (!valid) { Invalidate(); } enabled = valid; return valid; } catch { enabled = false; throw; } }
public static WaypointGenerator Create(ConfigNode configNode, WaypointGeneratorFactory factory) { WaypointGenerator wpGenerator = new WaypointGenerator(); bool valid = true; int index = 0; foreach (ConfigNode child in ConfigNodeUtil.GetChildNodes(configNode)) { DataNode dataNode = new DataNode("WAYPOINT_" + index, factory.dataNode, factory); try { ConfigNodeUtil.SetCurrentDataNode(dataNode); dataNode["type"] = child.name; double? altitude = null; WaypointData wpData = new WaypointData(child.name); // Use an expression to default - then it'll work for dynamic contracts if (!child.HasValue("targetBody")) { child.AddValue("targetBody", "@/targetBody.Name()"); } valid &= ConfigNodeUtil.ParseValue<string>(child, "targetBody", x => wpData.waypoint.celestialName = x, factory, Validation.CheckCelestialBody); valid &= ConfigNodeUtil.ParseValue<string>(child, "name", x => wpData.waypoint.name = x, factory, (string)null); valid &= ConfigNodeUtil.ParseValue<double?>(child, "altitude", x => altitude = x, factory, (double?)null); valid &= ConfigNodeUtil.ParseValue<string>(child, "parameter", x => wpData.parameter = x, factory, ""); valid &= ConfigNodeUtil.ParseValue<bool>(child, "hidden", x => wpData.waypoint.visible = !x, factory, false); if (!wpData.waypoint.visible) { valid &= ConfigNodeUtil.ParseValue<string>(child, "icon", x => wpData.waypoint.id = x, factory, ""); } else { valid &= ConfigNodeUtil.ParseValue<string>(child, "icon", x => wpData.waypoint.id = x, factory); } // The FinePrint logic is such that it will only look in Squad/Contracts/Icons for icons. // Cheat this by hacking the path in the game database. if (wpData.waypoint.id.Contains("/")) { GameDatabase.TextureInfo texInfo = GameDatabase.Instance.databaseTexture.Where(t => t.name == wpData.waypoint.id).FirstOrDefault(); if (texInfo != null) { texInfo.name = "Squad/Contracts/Icons/" + wpData.waypoint.id; } } // Track the index wpData.waypoint.index = index++; // Get altitude if (altitude == null) { wpData.waypoint.altitude = 0.0; wpData.randomAltitude = true; } else { wpData.waypoint.altitude = altitude.Value; } // Get settings that differ by type if (child.name == "WAYPOINT") { valid &= ConfigNodeUtil.ParseValue<double>(child, "latitude", x => wpData.waypoint.latitude = x, factory); valid &= ConfigNodeUtil.ParseValue<double>(child, "longitude", x => wpData.waypoint.longitude = x, factory); } else if (child.name == "RANDOM_WAYPOINT") { // Get settings for randomization valid &= ConfigNodeUtil.ParseValue<bool>(child, "waterAllowed", x => wpData.waterAllowed = x, factory, true); valid &= ConfigNodeUtil.ParseValue<bool>(child, "forceEquatorial", x => wpData.forceEquatorial = x, factory, false); valid &= ConfigNodeUtil.ParseValue<int>(child, "count", x => wpData.count = x, factory, 1, x => Validation.GE(x, 1)); } else if (child.name == "RANDOM_WAYPOINT_NEAR") { // Get settings for randomization valid &= ConfigNodeUtil.ParseValue<bool>(child, "waterAllowed", x => wpData.waterAllowed = x, factory, true); // Get near waypoint details valid &= ConfigNodeUtil.ParseValue<int>(child, "nearIndex", x => wpData.nearIndex = x, factory, x => Validation.GE(x, 0) && Validation.LT(x, wpGenerator.waypoints.Count)); valid &= ConfigNodeUtil.ParseValue<int>(child, "count", x => wpData.count = x, factory, 1, x => Validation.GE(x, 1)); // Get distances valid &= ConfigNodeUtil.ParseValue<double>(child, "minDistance", x => wpData.minDistance = x, factory, 0.0, x => Validation.GE(x, 0.0)); valid &= ConfigNodeUtil.ParseValue<double>(child, "maxDistance", x => wpData.maxDistance = x, factory, x => Validation.GT(x, wpData.minDistance)); } else if (child.name == "PQS_CITY") { wpData.randomAltitude = false; string pqsCity = null; valid &= ConfigNodeUtil.ParseValue<string>(child, "pqsCity", x => pqsCity = x, factory); if (pqsCity != null && !string.IsNullOrEmpty(wpData.waypoint.celestialName)) { try { CelestialBody body = FlightGlobals.Bodies.Where(b => b.name == wpData.waypoint.celestialName).First(); wpData.pqsCity = body.GetComponentsInChildren<PQSCity>(true).Where(pqs => pqs.name == pqsCity).First(); } catch (Exception e) { LoggingUtil.LogError(typeof(WaypointGenerator), "Couldn't load PQSCity with name '" + pqsCity + "'"); LoggingUtil.LogException(e); valid = false; } } valid &= ConfigNodeUtil.ParseValue<Vector3d>(child, "pqsOffset", x => wpData.pqsOffset = x, factory, new Vector3d()); } else { LoggingUtil.LogError(factory, "Unrecognized waypoint node: '" + child.name + "'"); valid = false; } // Check for unexpected values valid &= ConfigNodeUtil.ValidateUnexpectedValues(child, factory); // Generate a random name if (!child.HasValue("name")) { wpData.randomName = true; } // Add to the list wpGenerator.waypoints.Add(wpData); } finally { ConfigNodeUtil.SetCurrentDataNode(factory.dataNode); } } return valid ? wpGenerator : null; }
public static SpawnKerbal Create(ConfigNode configNode, SpawnKerbalFactory factory) { SpawnKerbal spawnKerbal = new SpawnKerbal(); bool valid = true; int index = 0; foreach (ConfigNode child in ConfigNodeUtil.GetChildNodes(configNode, "KERBAL")) { DataNode dataNode = new DataNode("KERBAL_" + index++, factory.dataNode, factory); try { ConfigNodeUtil.SetCurrentDataNode(dataNode); KerbalData kerbal = new KerbalData(); // Get name valid &= ConfigNodeUtil.ParseValue<string>(child, "name", x => { kerbal.name = x; if (kerbal.crewMember != null) kerbal.crewMember.name = x; }, factory, (string)null); // Use an expression to default - then it'll work for dynamic contracts if (!child.HasValue("targetBody")) { child.AddValue("targetBody", "@/targetBody"); } valid &= ConfigNodeUtil.ParseValue<CelestialBody>(child, "targetBody", x => kerbal.body = x, factory); // Get landed stuff if (child.HasValue("lat") && child.HasValue("lon") || child.HasValue("pqsCity")) { kerbal.landed = true; if (child.HasValue("pqsCity")) { string pqsCityStr = null; valid &= ConfigNodeUtil.ParseValue<string>(child, "pqsCity", x => pqsCityStr = x, factory); if (pqsCityStr != null) { try { kerbal.pqsCity = kerbal.body.GetComponentsInChildren<PQSCity>(true).Where(pqs => pqs.name == pqsCityStr).First(); } catch (Exception e) { LoggingUtil.LogError(typeof(WaypointGenerator), "Couldn't load PQSCity with name '" + pqsCityStr + "'"); LoggingUtil.LogException(e); valid = false; } } valid &= ConfigNodeUtil.ParseValue<Vector3d>(child, "pqsOffset", x => kerbal.pqsOffset = x, factory, new Vector3d()); // Don't expect these to load anything, but do it to mark as initialized valid &= ConfigNodeUtil.ParseValue<double>(child, "lat", x => kerbal.latitude = x, factory, 0.0); valid &= ConfigNodeUtil.ParseValue<double>(child, "lon", x => kerbal.longitude = x, factory, 0.0); } else { valid &= ConfigNodeUtil.ParseValue<double>(child, "lat", x => kerbal.latitude = x, factory); valid &= ConfigNodeUtil.ParseValue<double>(child, "lon", x => kerbal.longitude = x, factory); } valid &= ConfigNodeUtil.ParseValue<float>(child, "heading", x => kerbal.heading = x, factory, 0.0f); } // Get orbit else if (child.HasNode("ORBIT")) { // Don't expect these to load anything, but do it to mark as initialized valid &= ConfigNodeUtil.ParseValue<double>(child, "lat", x => kerbal.latitude = x, factory, 0.0); valid &= ConfigNodeUtil.ParseValue<double>(child, "lon", x => kerbal.longitude = x, factory, 0.0); valid &= ConfigNodeUtil.ParseValue<Orbit>(child, "ORBIT", x => kerbal.orbit = x, factory); } else { // Will error valid &= ConfigNodeUtil.ValidateMandatoryChild(child, "ORBIT", factory); } valid &= ConfigNodeUtil.ParseValue<double?>(child, "alt", x => kerbal.altitude = x, factory, (double?)null); // Get additional stuff valid &= ConfigNodeUtil.ParseValue<bool>(child, "owned", x => kerbal.owned = x, factory, false); valid &= ConfigNodeUtil.ParseValue<bool>(child, "addToRoster", x => kerbal.addToRoster = x, factory, true); valid &= ConfigNodeUtil.ParseValue<ProtoCrewMember.Gender?>(child, "gender", x => kerbal.gender = x, factory, (ProtoCrewMember.Gender?)null); valid &= ConfigNodeUtil.ParseValue<ProtoCrewMember.KerbalType>(child, "kerbalType", x => kerbal.kerbalType = x, factory, ProtoCrewMember.KerbalType.Unowned); // Check for unexpected values valid &= ConfigNodeUtil.ValidateUnexpectedValues(child, factory); // Add to the list spawnKerbal.kerbals.Add(kerbal); } finally { ConfigNodeUtil.SetCurrentDataNode(factory.dataNode); } } return valid ? spawnKerbal : null; }
/// <summary> /// Loads the ITERATOR nodes. /// </summary> /// <param name="node"></param> /// <returns>Whether the load was successful</returns> public static bool LoadIteratorNodes(ConfigNode node, IContractConfiguratorFactory obj) { bool valid = true; IEnumerable <ConfigNode> iteratorNodes = ConfigNodeUtil.GetChildNodes(node, "ITERATOR"); if (!iteratorNodes.Any()) { return(true); } else if (iteratorNodes.Count() > 1) { LoggingUtil.LogError(obj, "Multiple ITERATOR nodes found - only one iterator node allowed."); return(false); } ConfigNode iteratorNode = iteratorNodes.First(); DataNode iteratorDataNode = new DataNode("ITERATOR", obj.dataNode, obj); try { ConfigNodeUtil.SetCurrentDataNode(iteratorDataNode); valid &= ConfigNodeUtil.ParseValue <Type>(iteratorNode, "type", x => obj.iteratorType = x, obj); if (obj.iteratorType != null) { foreach (ConfigNode.Value pair in iteratorNode.values) { string name = pair.name; if (name != "type") { if (!string.IsNullOrEmpty(obj.iteratorKey)) { LoggingUtil.LogError(obj, "Multiple key values found in ITERATOR node - only one key allowed."); return(false); } // Create the list type Type listType = typeof(List <>); listType = listType.MakeGenericType(new Type[] { obj.iteratorType }); // Create the setter function object value = null; Type listActionType = typeof(Action <>).MakeGenericType(listType); Delegate listDelegate = Delegate.CreateDelegate(listActionType, value, typeof(DataNode).GetMethod("NullAction")); // Get the ParseValue method MethodInfo parseListMethod = parseMethodGeneric.MakeGenericMethod(new Type[] { listType }); // Invoke the ParseValue method valid &= (bool)parseListMethod.Invoke(null, new object[] { iteratorNode, name, listDelegate, obj }); // Store the iterator key for later obj.iteratorKey = name; } } } // Load didn't get us a key if (string.IsNullOrEmpty(obj.iteratorKey)) { LoggingUtil.LogError(obj, "No key field was defined for the ITERATOR!."); return(false); } } finally { ConfigNodeUtil.SetCurrentDataNode(obj.dataNode); } // Add a dummy value to the parent data node node.AddValue(obj.iteratorKey, "@ITERATOR/" + obj.iteratorKey + ".ElementAt(IteratorCurrentIndex())"); node.AddValue("iteratorCount", "@ITERATOR/" + obj.iteratorKey + ".Count()"); return(valid); }
public static OrbitGenerator Create(ConfigNode configNode, OrbitGeneratorFactory factory) { OrbitGenerator obGenerator = new OrbitGenerator(); bool valid = true; int index = 0; foreach (ConfigNode child in ConfigNodeUtil.GetChildNodes(configNode)) { DataNode dataNode = new DataNode("ORBIT_" + index++, factory.dataNode, factory); try { ConfigNodeUtil.SetCurrentDataNode(dataNode); OrbitData obData = new OrbitData(child.name); // Get settings that differ by type if (child.name == "FIXED_ORBIT") { valid &= ConfigNodeUtil.ParseValue<Orbit>(child, "ORBIT", x => obData.orbit = x, factory); } else if (child.name == "RANDOM_ORBIT") { valid &= ConfigNodeUtil.ParseValue<OrbitType>(child, "type", x => obData.orbitType = x, factory); valid &= ConfigNodeUtil.ParseValue<int>(child, "count", x => obData.count = x, factory, 1, x => Validation.GE(x, 1)); valid &= ConfigNodeUtil.ParseValue<double>(child, "altitudeFactor", x => obData.altitudeFactor = x, factory, 0.8, x => Validation.Between(x, 0.0, 1.0)); valid &= ConfigNodeUtil.ParseValue<double>(child, "inclinationFactor", x => obData.inclinationFactor = x, factory, 0.8, x => Validation.Between(x, 0.0, 1.0)); valid &= ConfigNodeUtil.ParseValue<double>(child, "eccentricity", x => obData.eccentricity = x, factory, 0.0, x => Validation.GE(x, 0.0)); valid &= ConfigNodeUtil.ParseValue<double>(child, "deviationWindow", x => obData.deviationWindow = x, factory, 10.0, x => Validation.GE(x, 0.0)); } else { throw new ArgumentException("Unrecognized orbit node: '" + child.name + "'"); } // Use an expression to default - then it'll work for dynamic contracts if (!child.HasValue("targetBody")) { child.AddValue("targetBody", "@/targetBody"); } valid &= ConfigNodeUtil.ParseValue<CelestialBody>(child, "targetBody", x => obData.targetBody = x, factory); // Check for unexpected values valid &= ConfigNodeUtil.ValidateUnexpectedValues(child, factory); // Add to the list obGenerator.orbits.Add(obData); } finally { ConfigNodeUtil.SetCurrentDataNode(factory.dataNode); } } allOrbitGenerators.Add(obGenerator); return valid ? obGenerator : null; }
/// <summary> /// Loads the contract type details from the given config node. /// </summary> /// <param name="configNode">The config node to load from.</param> /// <returns>Whether the load was successful.</returns> public bool Load(ConfigNode configNode) { LoggingUtil.LogLevel origLogLevel = LoggingUtil.logLevel; try { // Logging on LoggingUtil.CaptureLog = true; dataNode = new DataNode(configNode.GetValue("name"), this); ConfigNodeUtil.SetCurrentDataNode(dataNode); bool valid = true; valid &= ConfigNodeUtil.ParseValue<string>(configNode, "name", x => name = x, this); // Try to turn on trace mode valid &= ConfigNodeUtil.ParseValue<bool>(configNode, "trace", x => trace = x, this, false); if (trace) { LoggingUtil.logLevel = LoggingUtil.LogLevel.VERBOSE; LoggingUtil.LogWarning(this, "Tracing enabled for contract type " + name); } // Load contract text details valid &= ConfigNodeUtil.ParseValue<ContractGroup>(configNode, "group", x => group = x, this, (ContractGroup)null); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "title", x => title = x, this); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "tag", x => tag = x, this, ""); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "description", x => description = x, this, (string)null); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "topic", x => topic = x, this, (string)null); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "subject", x => subject = x, this, (string)null); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "motivation", x => motivation = x, this, (string)null); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "notes", x => notes = x, this, (string)null); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "synopsis", x => synopsis = x, this); valid &= ConfigNodeUtil.ParseValue<string>(configNode, "completedMessage", x => completedMessage = x, this); // Load optional attributes valid &= ConfigNodeUtil.ParseValue<Agent>(configNode, "agent", x => agent = x, this, (Agent)null); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "minExpiry", x => minExpiry = x, this, 1.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "maxExpiry", x => maxExpiry = x, this, 7.0f, x => Validation.GE(x, minExpiry)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "deadline", x => deadline = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<bool>(configNode, "cancellable", x => cancellable = x, this, true); valid &= ConfigNodeUtil.ParseValue<bool>(configNode, "declinable", x => declinable = x, this, true); valid &= ConfigNodeUtil.ParseValue<bool>(configNode, "autoAccept", x => autoAccept = x, this, false); valid &= ConfigNodeUtil.ParseValue<List<Contract.ContractPrestige>>(configNode, "prestige", x => prestige = x, this, new List<Contract.ContractPrestige>()); valid &= ConfigNodeUtil.ParseValue<CelestialBody>(configNode, "targetBody", x => targetBody = x, this, (CelestialBody)null); valid &= ConfigNodeUtil.ParseValue<int>(configNode, "maxCompletions", x => maxCompletions = x, this, 0, x => Validation.GE(x, 0)); valid &= ConfigNodeUtil.ParseValue<int>(configNode, "maxSimultaneous", x => maxSimultaneous = x, this, 0, x => Validation.GE(x, 0)); // Load rewards valid &= ConfigNodeUtil.ParseValue<float>(configNode, "rewardFunds", x => rewardFunds = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "rewardReputation", x => rewardReputation = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "rewardScience", x => rewardScience = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "failureFunds", x => failureFunds = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "failureReputation", x => failureReputation = x, this, 0.0f, x => Validation.GE(x, 0.0f)); valid &= ConfigNodeUtil.ParseValue<float>(configNode, "advanceFunds", x => advanceFunds = x, this, 0.0f, x => Validation.GE(x, 0.0f)); // Load other values valid &= ConfigNodeUtil.ParseValue<double>(configNode, "weight", x => weight = x, this, 1.0, x => Validation.GE(x, 0.0f)); // Load DATA nodes valid &= DataNode.ParseDataNodes(configNode, this, dataValues, uniqueValues); // Check for unexpected values - always do this last valid &= ConfigNodeUtil.ValidateUnexpectedValues(configNode, this); log = LoggingUtil.capturedLog; LoggingUtil.CaptureLog = false; // Load parameters foreach (ConfigNode contractParameter in ConfigNodeUtil.GetChildNodes(configNode, "PARAMETER")) { ParameterFactory paramFactory = null; valid &= ParameterFactory.GenerateParameterFactory(contractParameter, this, out paramFactory); if (paramFactory != null) { paramFactories.Add(paramFactory); if (paramFactory.hasWarnings) { hasWarnings = true; } } } // Load behaviours foreach (ConfigNode requirementNode in ConfigNodeUtil.GetChildNodes(configNode, "BEHAVIOUR")) { BehaviourFactory behaviourFactory = null; valid &= BehaviourFactory.GenerateBehaviourFactory(requirementNode, this, out behaviourFactory); if (behaviourFactory != null) { behaviourFactories.Add(behaviourFactory); if (behaviourFactory.hasWarnings) { hasWarnings = true; } } } // Load requirements foreach (ConfigNode requirementNode in ConfigNodeUtil.GetChildNodes(configNode, "REQUIREMENT")) { ContractRequirement requirement = null; valid &= ContractRequirement.GenerateRequirement(requirementNode, this, out requirement); if (requirement != null) { requirements.Add(requirement); if (requirement.hasWarnings) { hasWarnings = true; } } } // Logging on LoggingUtil.CaptureLog = true; // Check we have at least one valid parameter if (paramFactories.Count() == 0) { LoggingUtil.LogError(this.GetType(), ErrorPrefix() + ": Need at least one parameter for a contract!"); valid = false; } // Do the deferred loads valid &= ConfigNodeUtil.ExecuteDeferredLoads(); config = configNode.ToString(); hash = config.GetHashCode(); enabled = valid; log += LoggingUtil.capturedLog; LoggingUtil.CaptureLog = false; return valid; } catch { enabled = false; throw; } finally { LoggingUtil.logLevel = origLogLevel; loaded = true; } }
public override bool Load(ConfigNode configNode) { // Load base class bool valid = base.Load(configNode); int index = 0; foreach (ConfigNode child in ConfigNodeUtil.GetChildNodes(configNode, "DIALOG_BOX")) { string dialogBoxNode = "DIALOG_BOX_" + index++; DataNode childDataNode = new DataNode(dialogBoxNode, dataNode, this); try { ConfigNodeUtil.SetCurrentDataNode(childDataNode); DialogBox.DialogDetail detail = new DialogBox.DialogDetail(); details.Add(detail); valid &= ConfigNodeUtil.ParseValue<DialogBox.TriggerCondition>(child, "condition", x => detail.condition = x, this); valid &= ConfigNodeUtil.ParseValue<DialogBox.Position>(child, "position", x => detail.position = x, this, DialogBox.Position.LEFT); valid &= ConfigNodeUtil.ParseValue<float>(child, "width", x => detail.width = x, this, 0.8f, x => Validation.Between(x, 0.0f, 1.0f)); valid &= ConfigNodeUtil.ParseValue<float>(child, "height", x => detail.height = x, this, 0.0f, x => Validation.Between(x, 0.0f, 1.0f)); valid &= ConfigNodeUtil.ParseValue<string>(child, "title", x => detail.title = x, this, ""); valid &= ConfigNodeUtil.ParseValue<Color>(child, "titleColor", x => detail.titleColor = x, this, Color.white); valid &= ConfigNodeUtil.ParseValue<string>(child, "parameter", x => detail.parameter = x, this, (string)null, x => ValidateMandatoryParameter(x, detail.condition)); int sectionIndex = 0; foreach (ConfigNode sectionNode in child.GetNodes()) { DataNode sectionDataNode = new DataNode(dialogBoxNode + "_" + sectionIndex++, childDataNode, this); ConfigNodeUtil.SetCurrentDataNode(sectionDataNode); if (sectionNode.name == "TEXT") { DialogBox.TextSection section = new DialogBox.TextSection(); detail.sections.Add(section); // Parse the text twice, once to ensure parsability, the other to get the unexpanded text valid &= ConfigNodeUtil.ParseValue<string>(sectionNode, "text", x => { }, this); if (valid) { section.text = ConfigNodeUtil.ParseValue<string>(sectionNode, "text"); } valid &= ConfigNodeUtil.ParseValue<Color>(sectionNode, "textColor", x => section.textColor = x, this, new Color(0.8f, 0.8f, 0.8f)); valid &= ConfigNodeUtil.ParseValue<int>(sectionNode, "fontSize", x => section.fontSize = x, this, 20); } else if (sectionNode.name == "IMAGE") { DialogBox.ImageSection section = new DialogBox.ImageSection(); detail.sections.Add(section); valid &= ConfigNodeUtil.ParseValue<string>(sectionNode, "url", x => section.imageURL = x, this, ValidateImageURL); valid &= ConfigNodeUtil.ParseValue<string>(sectionNode, "characterName", x => { section.characterName = x; section.showName = !string.IsNullOrEmpty(x); }, this, ""); valid &= ConfigNodeUtil.ParseValue<Color>(sectionNode, "textColor", x => section.textColor = x, this, new Color(0.729f, 0.855f, 0.333f)); } else if (sectionNode.name == "INSTRUCTOR") { DialogBox.InstructorSection section = new DialogBox.InstructorSection(); detail.sections.Add(section); valid &= ConfigNodeUtil.ParseValue<string>(sectionNode, "name", x => section.name = x, this); valid &= ConfigNodeUtil.ParseValue<bool>(sectionNode, "showName", x => section.showName = x, this, true); valid &= ConfigNodeUtil.ParseValue<string>(sectionNode, "characterName", x => section.characterName = x, this, ""); valid &= ConfigNodeUtil.ParseValue<Color>(sectionNode, "textColor", x => section.textColor = x, this, new Color(0.729f, 0.855f, 0.333f)); valid &= ConfigNodeUtil.ParseValue<DialogBox.InstructorSection.Animation?>(sectionNode, "animation", x => section.animation = x, this, (DialogBox.InstructorSection.Animation?)null); } else if (sectionNode.name == "KERBAL") { DialogBox.KerbalSection section = new DialogBox.KerbalSection(); detail.sections.Add(section); valid &= ConfigNodeUtil.ParseValue<bool>(sectionNode, "showName", x => section.showName = x, this, true); valid &= ConfigNodeUtil.ParseValue<string>(sectionNode, "characterName", x => section.characterName = x, this, ""); valid &= ConfigNodeUtil.ParseValue<ProtoCrewMember.Gender>(sectionNode, "gender", x => section.gender = x, this, ProtoCrewMember.Gender.Male); valid &= ConfigNodeUtil.ParseValue<Color>(sectionNode, "textColor", x => section.textColor = x, this, new Color(0.729f, 0.855f, 0.333f)); valid &= ConfigNodeUtil.ParseValue<int>(sectionNode, "crewIndex", x => section.crewIndex = x, this, 0); valid &= ConfigNodeUtil.ParseValue<List<string>>(sectionNode, "excludeName", x => section.excludeName = x, this, new List<string>()); } else if (sectionNode.name == "BREAK") { DialogBox.BreakSection section = new DialogBox.BreakSection(); detail.sections.Add(section); } } } finally { ConfigNodeUtil.SetCurrentDataNode(dataNode); } } valid &= ConfigNodeUtil.ValidateMandatoryChild(configNode, "DIALOG_BOX", this); return valid; }
/// <summary> /// Loads the ITERATOR nodes. /// </summary> /// <param name="node"></param> /// <returns>Whether the load was successful</returns> public static bool LoadIteratorNodes(ConfigNode node, IContractConfiguratorFactory obj) { bool valid = true; IEnumerable<ConfigNode> iteratorNodes = ConfigNodeUtil.GetChildNodes(node, "ITERATOR"); if (!iteratorNodes.Any()) { return true; } else if (iteratorNodes.Count() > 1) { LoggingUtil.LogError(obj, "Multiple ITERATOR nodes found - only one iterator node allowed."); return false; } ConfigNode iteratorNode = iteratorNodes.First(); DataNode iteratorDataNode = new DataNode("ITERATOR", obj.dataNode, obj); try { ConfigNodeUtil.SetCurrentDataNode(iteratorDataNode); valid &= ConfigNodeUtil.ParseValue<Type>(iteratorNode, "type", x => obj.iteratorType = x, obj); if (obj.iteratorType != null) { foreach (ConfigNode.Value pair in iteratorNode.values) { string name = pair.name; if (name != "type") { if (!string.IsNullOrEmpty(obj.iteratorKey)) { LoggingUtil.LogError(obj, "Multiple key values found in ITERATOR node - only one key allowed."); return false; } // Create the list type Type listType = typeof(List<>); listType = listType.MakeGenericType(new Type[] { obj.iteratorType }); // Create the setter function object value = null; Type listActionType = typeof(Action<>).MakeGenericType(listType); Delegate listDelegate = Delegate.CreateDelegate(listActionType, value, typeof(DataNode).GetMethod("NullAction")); // Get the ParseValue method MethodInfo parseListMethod = parseMethodGeneric.MakeGenericMethod(new Type[] { listType }); // Invoke the ParseValue method valid &= (bool)parseListMethod.Invoke(null, new object[] { iteratorNode, name, listDelegate, obj }); // Store the iterator key for later obj.iteratorKey = name; } } } // Load didn't get us a key if (string.IsNullOrEmpty(obj.iteratorKey)) { LoggingUtil.LogError(obj, "No key field was defined for the ITERATOR!."); return false; } } finally { ConfigNodeUtil.SetCurrentDataNode(obj.dataNode); } // Add a dummy value to the parent data node node.AddValue(obj.iteratorKey, "@ITERATOR/" + obj.iteratorKey + ".ElementAt(IteratorCurrentIndex())"); node.AddValue("iteratorCount", "@ITERATOR/" + obj.iteratorKey + ".Count()"); return valid; }
public override void OnGUI() { if (labelStyle == null) { labelStyle = new GUIStyle(UnityEngine.GUI.skin.label); labelStyle.alignment = TextAnchor.UpperLeft; labelStyle.richText = true; labelStyle.normal.textColor = textColor; labelStyle.fontSize = fontSize; } if (expandedText == null) { DataNode emptyNode = new DataNode("empty", null); ExpressionParser<string> parser = BaseParser.GetParser<string>(); expandedText = parser.ExecuteExpression("null", text, emptyNode); } GUILayout.Label(expandedText, labelStyle, GUILayout.ExpandWidth(true)); }
public bool IsChildOf(DataNode node) { for (DataNode p = this; p != null; p = p.parent) { if (node == p) { return true; } } return false; }
static string DataNodeDebug(DataNode node, int indent = 0) { if (node == null) { return ""; } string indentStr = new string('\t', indent); string result = indentStr + node.DebugString().Replace("\n", "\n" + indentStr) + "\n"; foreach (DataNode child in node.Children) { if (child.Factory == node.Factory) { result += DataNodeDebug(child, indent + 1); } } return result; }
protected static T SelectUnique(List <T> input) { // Check if there's no values if (input == null || !input.Any()) { return(default(T)); } // Get details from the base parser ContractType contractType = BaseParser.currentParser.currentDataNode.Root.Factory as ContractType; string key = BaseParser.currentParser.currentKey; DataNode.UniquenessCheck uniquenessCheck = contractType.uniquenessChecks.ContainsKey(key) ? contractType.uniquenessChecks[key] : DataNode.UniquenessCheck.NONE; DataNode dataNode = BaseParser.currentParser.currentDataNode; // Provide warning of a better method if (dataNode != null && dataNode.IsDeterministic(key) && (uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ALL || uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ACTIVE)) { IContractConfiguratorFactory factory = BaseParser.currentParser.currentDataNode.Factory; LoggingUtil.LogWarning(factory, factory.ErrorPrefix() + ": Consider using a DATA_EXPAND node instead of the SelectUnique function when the values are deterministic - this will cause the player to see the full set of values in mission control before the contract is offered."); } // Check for properly uniquness check if (uniquenessCheck == DataNode.UniquenessCheck.NONE) { throw new NotSupportedException("The SelectUnique method can only be used in DATA nodes with the uniquenessCheck attribute set."); } // Get the active/offered contract lists IEnumerable <ConfiguredContract> contractList = ConfiguredContract.CurrentContracts. Where(c => c != null && c.contractType != null); // Add in finished contracts if (uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ALL || uniquenessCheck == DataNode.UniquenessCheck.GROUP_ALL) { contractList = contractList.Union(ConfiguredContract.CompletedContracts. Where(c => c != null && c.contractType != null)); } // Filter anything that doesn't have our key contractList = contractList.Where(c => c.uniqueData.ContainsKey(key)); // Check for contracts of the same type if (uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ALL || uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ACTIVE) { contractList = contractList.Where(c => c.contractType.name == contractType.name); } // Check for a shared group else if (contractType.group != null) { contractList = contractList.Where(c => c.contractType.group != null && c.contractType.group.name == contractType.group.name); } // Shared lack of group else { contractList = contractList.Where(c => c.contractType.group == null); } // Get the valid values IEnumerable <T> values; // Special case for vessels if (typeof(T) == typeof(Vessel)) { values = input.Where(t => !contractList.Any(c => c.uniqueData[key].Equals(((Vessel)(object)t).id))); } else { values = input.Where(t => !contractList.Any(c => c.uniqueData[key].Equals(t))); } // Make a random selection from what's left return(values.Skip(r.Next(values.Count())).FirstOrDefault()); }