fix(advanced-search): E — descending sort last page renders its items

The paging loop in AdvancedSearchGump.Build assumed a full MaxEntries
page: on a partial last page in descending mode, the first iteration's
index already overflowed SearchResults.Length, and the break early-out
killed the whole loop, rendering zero rows.

Add a VisibleCount(total, displayFrom, maxEntries) helper and bound the
loop to it instead of MaxEntries, generalizing the descending offset
formula (MaxEntries - 1 - i -> visibleCount - 1 - i) so it stays valid
for partial pages while being identical to the old formula on full
pages.
This commit is contained in:
Kamron Batman 2026-07-19 22:03:17 -07:00
parent 677a054448
commit 3a4dee0bf1
2 changed files with 30 additions and 8 deletions

View file

@ -0,0 +1,17 @@
using Server.Engines.AdvancedSearch;
using Xunit;
namespace UOContent.Tests;
public class AdvancedSearchPagingTests
{
[Theory]
[InlineData(20, 0, 18, 18)] // full first page
[InlineData(20, 18, 18, 2)] // partial last page -> 2 visible (bug rendered 0 in descending)
[InlineData(5, 0, 18, 5)]
[InlineData(0, 0, 18, 0)]
public void VisibleCount_IsCorrect(int total, int from, int max, int expected)
{
Assert.Equal(expected, AdvancedSearchGump.VisibleCount(total, from, max));
}
}

View file

@ -130,6 +130,12 @@ public class AdvancedSearchGump : Gump
public AdvancedSearchGump() : base(50, 50) => Build();
// Number of result entries that actually fit on the current page, given how many
// remain after DisplayFrom. Prevents the paging loop from reading/rendering past
// the end of SearchResults on a partial last page.
internal static int VisibleCount(int total, int displayFrom, int maxEntries) =>
Math.Clamp(total - displayFrom, 0, maxEntries);
private void Build()
{
const int height = 500;
@ -325,15 +331,14 @@ public class AdvancedSearchGump : Gump
var allDisplayedSelected = true;
for (var i = 0; i < MaxEntries; i++)
{
var offset = SortDescending ? MaxEntries - 1 - i : i;
var index = offset + DisplayFrom;
// Bounded to the entries that actually exist on this page so a partial last
// page (fewer than MaxEntries remaining) still renders in descending mode.
var visibleCount = VisibleCount(SearchResults.Length, DisplayFrom, MaxEntries);
if (index >= SearchResults.Length)
{
break;
}
for (var i = 0; i < visibleCount; i++)
{
var offset = SortDescending ? visibleCount - 1 - i : i;
var index = offset + DisplayFrom;
var entry = SearchResults[index];