Merge pull request #221 from simoleo89/fix/catalog-search-results

fix(catalog): repair search offer ids
This commit is contained in:
DuckieTM
2026-06-17 09:55:26 +02:00
committed by GitHub
4 changed files with 76 additions and 7 deletions
@@ -174,6 +174,14 @@ public class CatalogItem implements ISerialize, Runnable, Comparable<CatalogItem
return this.offerId;
}
public int getSearchOfferId() {
if (this.offerId > 0) {
return this.offerId;
}
return haveOffer(this) ? this.id : -1;
}
public boolean isLimited() {
return this.limitedStack > 0;
}
@@ -494,10 +494,11 @@ public class CatalogManager {
item = new CatalogItem(set);
page.addItem(item);
if (item.getOfferId() != -1) {
page.addOfferId(item.getOfferId());
int searchOfferId = item.getSearchOfferId();
if (searchOfferId != -1) {
page.addOfferId(searchOfferId);
this.offerDefs.put(item.getOfferId(), item.getId());
this.offerDefs.put(searchOfferId, item.getId());
}
} else
item.update(set);
@@ -12,10 +12,15 @@ public class CatalogSearchedItemEvent extends MessageHandler {
public void handle() throws Exception {
int offerId = this.packet.readInt();
int pageId = Emulator.getGameEnvironment().getCatalogManager().offerDefs.get(offerId);
int catalogItemId = Emulator.getGameEnvironment().getCatalogManager().offerDefs.get(offerId);
if (pageId != 0) {
CatalogPage page = Emulator.getGameEnvironment().getCatalogManager().getCatalogPage(Emulator.getGameEnvironment().getCatalogManager().getCatalogItem(pageId).getPageId());
if (catalogItemId != 0) {
CatalogItem requestedItem = Emulator.getGameEnvironment().getCatalogManager().getCatalogItem(catalogItemId);
if (requestedItem == null) {
return;
}
CatalogPage page = Emulator.getGameEnvironment().getCatalogManager().getCatalogPage(requestedItem.getPageId());
if (page != null) {
TIntObjectIterator<CatalogItem> iterator = page.getCatalogItems().iterator();
@@ -25,7 +30,7 @@ public class CatalogSearchedItemEvent extends MessageHandler {
CatalogItem item = iterator.value();
if (item.getOfferId() == offerId) {
if (item.getSearchOfferId() == offerId) {
this.client.sendResponse(new CatalogSearchResultComposer(item));
return;
}
@@ -0,0 +1,55 @@
package com.eu.habbo.messages.incoming.catalog;
import org.junit.jupiter.api.Test;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.jupiter.api.Assertions.assertTrue;
class CatalogSearchOfferIdContractTest {
private static String source(String path) throws Exception {
return Files.readString(Path.of(path));
}
@Test
void catalogItemsExposeStableSearchOfferIdWhenDatabaseOfferIdIsMissing() throws Exception {
String source = source("src/main/java/com/eu/habbo/habbohotel/catalog/CatalogItem.java");
int method = source.indexOf("public int getSearchOfferId()");
int rawGuard = source.indexOf("this.offerId > 0", method);
int fallback = source.indexOf("return haveOffer(this) ? this.id : -1", rawGuard);
assertTrue(method > -1, "CatalogItem should expose a search-safe offer id");
assertTrue(rawGuard > method, "CatalogItem should preserve valid positive database offer ids");
assertTrue(fallback > rawGuard,
"CatalogItem should fall back to catalog item id when offer_id is missing but the item can be offered");
}
@Test
void catalogManagerIndexesSearchOfferIdsInsteadOfRawOfferIds() throws Exception {
String source = source("src/main/java/com/eu/habbo/habbohotel/catalog/CatalogManager.java");
int searchOffer = source.indexOf("int searchOfferId = item.getSearchOfferId()");
int addOffer = source.indexOf("page.addOfferId(searchOfferId)", searchOffer);
int offerDefs = source.indexOf("this.offerDefs.put(searchOfferId, item.getId())", addOffer);
assertTrue(searchOffer > -1, "CatalogManager should calculate the runtime search offer id");
assertTrue(addOffer > searchOffer, "CatalogManager should expose runtime search offer ids in catalog pages");
assertTrue(offerDefs > addOffer, "CatalogManager should map runtime search offer ids back to catalog items");
assertTrue(!source.contains("this.offerDefs.put(item.getOfferId(), item.getId())"),
"CatalogManager must not index raw -1 offer ids for catalog search");
}
@Test
void catalogSearchLookupResolvesCatalogItemIdsAndComparesSearchOfferIds() throws Exception {
String source = source("src/main/java/com/eu/habbo/messages/incoming/catalog/CatalogSearchedItemEvent.java");
assertTrue(source.contains("int catalogItemId ="),
"Catalog search lookup should name offerDefs values as catalog item ids");
assertTrue(source.contains("getCatalogItem(catalogItemId)"),
"Catalog search should resolve the mapped catalog item directly");
assertTrue(source.contains("item.getSearchOfferId() == offerId"),
"Catalog search should compare runtime search offer ids, not raw database offer ids");
}
}