From d8555f207ed44da310280f4501bdcde24161c236 Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Sat, 20 Sep 2025 03:53:26 +0200 Subject: [PATCH] Rework range check - Loops through all entries - Bumped amount of cols up to 8 for future proofing - Use Ordinal search - Actually parse ranges and check if the RowId is allowed --- .../Game/Text/Evaluator/SeStringEvaluator.cs | 87 ++++++++++++------- 1 file changed, 56 insertions(+), 31 deletions(-) diff --git a/Dalamud/Game/Text/Evaluator/SeStringEvaluator.cs b/Dalamud/Game/Text/Evaluator/SeStringEvaluator.cs index cd981ae75..424b2769a 100644 --- a/Dalamud/Game/Text/Evaluator/SeStringEvaluator.cs +++ b/Dalamud/Game/Text/Evaluator/SeStringEvaluator.cs @@ -1630,37 +1630,56 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator var isNoun = false; - Span cols = stackalloc int[2]; + var colIndex = 0; + Span cols = stackalloc int[8]; cols.Clear(); + var isInRange = false; - if (ranges.StartsWith("noun")) + while (!string.IsNullOrWhiteSpace(ranges)) { - isNoun = true; - } - else if (ranges.StartsWith("col")) - { - var i = 0; - while (i < cols.Length && ranges.StartsWith("col-", StringComparison.Ordinal)) + // find the end of the current entry + var entryEnd = ranges.IndexOf(','); + if (entryEnd == -1) + entryEnd = ranges.Length; + + if (ranges.StartsWith("noun", StringComparison.Ordinal)) { - // find the end of the current "col-#" token - var colRangeEnd = ranges.IndexOf(','); - if (colRangeEnd == -1) - colRangeEnd = ranges.Length; - - // parse the column index - cols[i++] = int.Parse(ranges.AsSpan(4, colRangeEnd - 4)); - - // if it's the end of the string, we're done - if (colRangeEnd == ranges.Length) - break; - - // move to the next entry - ranges = ranges[(colRangeEnd + 1)..].TrimStart(); + isNoun = true; } + else if (ranges.StartsWith("col", StringComparison.Ordinal) && colIndex < cols.Length) + { + cols[colIndex++] = int.Parse(ranges.AsSpan(4, entryEnd - 4)); + } + else if (ranges.StartsWith("tail", StringComparison.Ordinal)) + { + // currently not supported, since there are no known uses + context.Builder.Append(payload); + return false; + } + else + { + var dash = ranges.IndexOf('-'); + if (dash == -1) + { + isInRange |= int.Parse(ranges.AsSpan(0, entryEnd)) == rowId; + } + else + { + isInRange |= rowId >= int.Parse(ranges.AsSpan(0, dash)) + && rowId <= int.Parse(ranges.AsSpan(dash + 1, entryEnd - dash - 1)); + } + } + + // if it's the end of the string, we're done + if (entryEnd == ranges.Length) + break; + + // else, move to the next entry + ranges = ranges[(entryEnd + 1)..].TrimStart(); } - else if (ranges.StartsWith("tail")) + + if (!isInRange) { - // couldn't find any, so we don't handle them :p context.Builder.Append(payload); return false; } @@ -1678,15 +1697,21 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator } else if (this.dataManager.GetExcelSheet(context.Language, sheetName).TryGetRow(rowId, out var row)) { - // the game uses a priority system for columns here. - // if the first column is empty (for example MainCommand.Alias), then the next one is used (MainCommand.Command) - for (var i = 0; i < cols.Length; i++) + if (colIndex == 0) { - var text = row.ReadStringColumn(cols[i]); - if (!text.IsEmpty) + context.Builder.Append(row.ReadStringColumn(0)); + return true; + } + else + { + for (var i = 0; i < colIndex; i++) { - context.Builder.Append(text); - break; + var text = row.ReadStringColumn(cols[i]); + if (!text.IsEmpty) + { + context.Builder.Append(text); + break; + } } } }