/// <summary> /// Tries to get a single <see cref="ScriptingContextObject"/> by its path from the context. Throws an exception if multiple are found. /// </summary> /// <param name="scriptObject">The script object, that was found; otherwise <c>null</c>.</param> /// <param name="path">The path of the script object. The tuples have the format <c>(Block Name, Object Name)</c>.</param> /// <returns>Returns <c>true</c> if a script object was found; otherwise returns <c>false</c>.</returns> /// <example> /// <code> /// bool foundObj = TryGetObject(out ScriptingContextObject myObj, Tuple.Create("ai_squad", "sq_garage_cov_1"), Tuple.Create("ai_single_location", "spawn_points_3")); /// </code> /// </example> /// <exception cref="ScriptingContextException">Thrown when multiple context objects were found.</exception> public bool TryGetObjectSingle(out ScriptingContextObject scriptObject, params Tuple <string, string>[] path) { // Item1 = Block name // Item2 = Object name scriptObject = null; if (path.Length > 0 && TryGetObjects(out IEnumerable <ScriptingContextObject> objects, path)) { if (objects.Count() == 1) { scriptObject = objects.First(); return(true); } else { var lastPathTuple = path.Last(); throw new ScriptingContextException($"Failed to retrieve the single context object \"{lastPathTuple.Item2}\". " + $"The scripting context block \"{lastPathTuple.Item1}\" contained multiple objects with this name."); } } else { return(false); } }
/// <summary> /// Creates a context object from meta data. /// </summary> /// <param name="index">The index of the object.</param> /// <param name="group">The object group of the object.</param> /// <param name="isChildObject">is true if thi sobject is the child of another object.</param> /// <param name="data">The meta data.</param> /// <returns>A context object.</returns> private static ScriptingContextObject CreateContextObject(int index, string group, bool isChildObject, StructureValueCollection data, int wrapperIndex = -1) { string name = data.HasStringID("Name") ? data.GetStringID("Name") : data.GetString("Name"); var result = new ScriptingContextObject(name.ToLowerInvariant(), index, group, isChildObject, wrapperIndex); var childBlocks = data.GetTagBlocks(); if (childBlocks.Length > 0) { foreach (var block in childBlocks.Where(b => b.Value.Length > 0)) { // Handle child blocks, which are wrapped up in another block without a name field. if (IsWrapperBlock(block)) { var wrappedBlocks = new Dictionary <string, List <ScriptingContextObject> >(); // Iterate through the wrapper elements and collect all wrapped blocks and their objects. for (int i = 0; i < block.Value.Length; i++) { var innerChildrenBlocks = block.Value[i].GetTagBlocks(); foreach (var inner in innerChildrenBlocks) { var wrappedObjects = GetWrapperContextObjects(inner, i); if (wrappedBlocks.ContainsKey(inner.Key)) { wrappedBlocks[inner.Key].AddRange(wrappedObjects); } else { wrappedBlocks[inner.Key] = wrappedObjects.ToList(); } } } // Add the grouped blocks and objects to the result. foreach (var groupedBlock in wrappedBlocks) { result.AddChildBlock(new ScriptingContextBlock(groupedBlock.Key, groupedBlock.Value)); } } // Handle regular child blocks. else { result.AddChildBlock(CreateContextBlock(block, true)); } } } return(result); }
/// <summary> /// Tries to get a <see cref="ScriptingContextObject"/> by its path from the context. Returns the first object if multiple are found. /// </summary> /// <param name="scriptObject">The script object, that was found; otherwise <c>null</c>.</param> /// <param name="path">The path of the script object. The tuples have the format <c>(Block Name, Object Name)</c>.</param> /// <returns>Returns <c>true</c> if a script object was found; otherwise returns <c>false</c>.</returns> /// <example> /// <code> /// bool foundObj = TryGetObject(out ScriptingContextObject myObj, Tuple.Create("ai_squad", "sq_garage_cov_1"), Tuple.Create("ai_single_location", "spawn_points_3")); /// </code> /// </example> public bool TryGetObjectFirst(out ScriptingContextObject scriptObject, params Tuple <string, string>[] path) { // Item1 = Block name // Item2 = Object name scriptObject = null; if (path.Length > 0 && TryGetObjects(out IEnumerable <ScriptingContextObject> objects, path)) { scriptObject = objects.First(); return(true); } else { return(false); } }
public bool TryGetObjects(out IEnumerable <ScriptingContextObject> objects, params Tuple <string, string>[] path) { // Item1 = Block name // Item2 = Object name objects = new ScriptingContextObject[0]; if (_objectGroups.TryGetValue(path[0].Item1, out ScriptingContextBlock block)) { var result = block.GetObjects(path[0].Item2).ToArray(); if (!result.Any()) { return(false); } else if (path.Length == 1) { objects = result; return(true); } // Handle children. for (int i = 1; i < path.Length; i++) { // Just pick the first match for now. Duplicate names suck. if (!result[0].TryGetChildBlock(path[i].Item1, out ScriptingContextBlock childBlock)) { return(false); } result = childBlock.GetObjects(path[i].Item2).ToArray(); if (result.Length == 0) { return(false); } } objects = result; return(true); } return(false); }