private void ParseString() { String = GetCachedString(Value, Localized); if (String == null) { try { if (!Localized) { String = CustomStringGroup.ParseCustomString(Value, FormatParameters.Length); } else { String = LocalizedString.ParseLocalizedString(Value, 0, Value, FormatParameters.Length); } lock (_cacheLock) _cache.Add(String); } catch (StringParseFailedException ex) { if (ex.StringIndex == -1) { _parseInfo.Script.Diagnostics.Error(ex.Message, _stringRange); } else { int errorStart = _stringRange.Start.Character + 1 + ex.StringIndex; _parseInfo.Script.Diagnostics.Error(ex.Message, new DocRange( new DocPos(_stringRange.Start.Line, errorStart), new DocPos(_stringRange.Start.Line, errorStart + ex.Length) )); } } } _parseInfo.TranslateInfo.GetComponent <StringSaverComponent>().Strings.Add(String); }
public static CustomStringGroup ParseCustomString(string value, int parameterCount) { // Look for <#>s var formats = Regex.Matches(value, "<([0-9]+)>").ToArray(); CustomStringGroup customStringGroup = new CustomStringGroup(value); // If there are no formats, return the custom string normally. if (formats.Length == 0) { customStringGroup.Segments = new CustomStringSegment[] { new CustomStringSegment(value) }; return(customStringGroup); } // The Overwatch workshop only supports 3 formats in a string. // The following code will split the string into multiple sections so it can support more. // Split the string after every 3 unique formats, for example: // v split here // <0> this <1> <0> is a <3> custom <4> string <5> List <FormatParameter> stringGroupParameters = new List <FormatParameter>(); // The current group of formats. List <StringGroup> stringGroups = new List <StringGroup>(); // Stores information about each section in the string. List <int> unique = new List <int>(); // Stores the list of each unique format id. The count shouldn't go above 3. for (int i = 0; i < formats.Length; i++) { FormatParameter parameter = new FormatParameter(formats[i]); // If the format id is more than the number of parameters, throw a syntax error. if (parameter.Parameter >= parameterCount) { throw new StringParseFailedException( $"Can't set the <{parameter.Parameter}> format, there are only {parameterCount} parameters.", parameter.Match.Index, parameter.Match.Length ); } // If there is already 3 unique IDs, create a new section. if (unique.Count == 3 && !unique.Contains(parameter.Parameter)) { stringGroups.Add(new StringGroup(stringGroupParameters.ToArray())); stringGroupParameters.Clear(); unique.Clear(); } stringGroupParameters.Add(parameter); // If the current format ID is new, add it to the unique list. if (!unique.Contains(parameter.Parameter)) { unique.Add(parameter.Parameter); } } // Add tailing formats to a new section. stringGroups.Add(new StringGroup(stringGroupParameters.ToArray())); // Convert each section to a custom string. customStringGroup.Segments = new CustomStringSegment[stringGroups.Count]; for (int i = 0; i < stringGroups.Count; i++) { // start is either the start of the string or the end of the last section. int start = i == 0 ? 0 : stringGroups[i - 1].EndIndex; // end is the index of last format in the section unless this is the last section, then it will be the end of the string. int end = i == stringGroups.Count - 1 ? value.Length : stringGroups[i].EndIndex; string groupString = value.Substring(start, end - start); // Returns an array of all unique formats in the current section. var formatGroups = stringGroups[i].Formats .GroupBy(g => g.Parameter) .Select(g => g.First()) .ToArray(); // groupParameters is {0}, {1}, and {2}. Length should be between 1 and 3. int[] groupParameters = new int[formatGroups.Length]; for (int g = 0; g < formatGroups.Length; g++) { int parameter = formatGroups[g].Parameter; groupString = groupString.Replace("<" + parameter + ">", "{" + g + "}"); groupParameters[g] = parameter; } customStringGroup.Segments[i] = new CustomStringSegment(groupString, groupParameters); } return(customStringGroup); }