Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/map/atcommand.c
Original file line number Diff line number Diff line change
Expand Up @@ -3559,7 +3559,7 @@ ACMD(idsearch)

safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,77), item_name); // Search results for '%s' (name: id):
clif->message(fd, atcmd_output);
match = itemdb->search_name_array(item_array, MAX_SEARCH, item_name, 0);
match = itemdb->search_name_array(item_array, MAX_SEARCH, item_name, IT_SEARCH_NAME_PARTIAL);
if (match > MAX_SEARCH) {
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,269), MAX_SEARCH, match);
clif->message(fd, atcmd_output);
Expand Down Expand Up @@ -7441,7 +7441,7 @@ ACMD(iteminfo)
return false;
}
if ((item_array[0] = itemdb->exists(atoi(message))) == NULL)
count = itemdb->search_name_array(item_array, MAX_SEARCH, message, 0);
count = itemdb->search_name_array(item_array, MAX_SEARCH, message, IT_SEARCH_NAME_PARTIAL);

if (!count) {
clif->message(fd, msg_fd(fd,19)); // Invalid item ID or name.
Expand Down Expand Up @@ -7492,7 +7492,7 @@ ACMD(whodrops)
return false;
}
if ((item_array[0] = itemdb->exists(atoi(message))) == NULL)
count = itemdb->search_name_array(item_array, MAX_SEARCH, message, 0);
count = itemdb->search_name_array(item_array, MAX_SEARCH, message, IT_SEARCH_NAME_PARTIAL);

if (!count) {
clif->message(fd, msg_fd(fd,19)); // Invalid item ID or name.
Expand Down
2 changes: 1 addition & 1 deletion src/map/clif.c
Original file line number Diff line number Diff line change
Expand Up @@ -15268,7 +15268,7 @@ static void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd)

safestrncpy(item_monster_name, p->str, sizeof(item_monster_name));

if ( (count=itemdb->search_name_array(item_array, 10, item_monster_name, 1)) > 0 ) {
if ( (count=itemdb->search_name_array(item_array, 10, item_monster_name, IT_SEARCH_NAME_EXACT)) > 0 ) {
for(i = 0; i < count; i++) {
if( !item_array[i] )
continue;
Expand Down
136 changes: 84 additions & 52 deletions src/map/itemdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,73 +117,105 @@ static struct item_data *itemdb_name2id(const char *str)
*/
static int itemdb_searchname_array_sub(union DBKey key, struct DBData data, va_list ap)
{
struct item_data *item = DB->data2ptr(&data);
char *str;
str=va_arg(ap,char *);
struct item_data *itd = DB->data2ptr(&data);
const char *str = va_arg(ap, const char *);
enum item_name_search_flag flag = va_arg(ap, enum item_name_search_flag);

nullpo_ret(str);
if (item == &itemdb->dummy)

if (itd == &itemdb->dummy)
return 1; //Invalid item.
if(stristr(item->jname,str))
return 0;
if(battle_config.case_sensitive_aegisnames && strstr(item->name,str))
return 0;
if(!battle_config.case_sensitive_aegisnames && stristr(item->name,str))

if (
(flag == IT_SEARCH_NAME_PARTIAL
&& (stristr(itd->jname, str) != NULL
|| (battle_config.case_sensitive_aegisnames && strstr(itd->name, str))
|| (!battle_config.case_sensitive_aegisnames && stristr(itd->name, str))
))
|| (flag == IT_SEARCH_NAME_EXACT
&& (strcmp(itd->jname, str) == 0
|| (battle_config.case_sensitive_aegisnames && strcmp(itd->name, str) == 0)
|| (!battle_config.case_sensitive_aegisnames && strcasecmp(itd->name, str) == 0)
))
) {

return 0;
return strcmpi(item->jname,str);
} else {
return 1;
}
}

/*==========================================
* Founds up to N matches. Returns number of matches [Skotlex]
* search flag :
* 0 - approximate match
* 1 - exact match
*------------------------------------------*/
static int itemdb_searchname_array(struct item_data **data, int size, const char *str, int flag)
/**
* Finds up to passed size matches
* @param data array of struct item_data for returning the results in
* @param size size of the array
* @param str string used in this search
* @param flag search mode refer to enum item_name_search_flag for possible values
* @return returns all found matches in the database which could be bigger than size
**/
static int itemdb_searchname_array(struct item_data **data, const int size, const char *str, enum item_name_search_flag flag)
{
struct item_data* item;
int i;
int count=0;

nullpo_ret(data);
nullpo_ret(str);
// Search in the array
for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i )
{
item = itemdb->array[i];
if( item == NULL )
Assert_ret(flag >= IT_SEARCH_NAME_PARTIAL && flag < IT_SEARCH_NAME_MAX);
Assert_ret(size > 0);

int
results_count = 0,
length = 0;

// Search in array
for (int i = 0; i < ARRAYLENGTH(itemdb->array); ++i) {
struct item_data *itd = itemdb->array[i];

if (itd == NULL)
continue;

if(
(!flag
&& (stristr(item->jname,str)
|| (battle_config.case_sensitive_aegisnames && strstr(item->name,str))
|| (!battle_config.case_sensitive_aegisnames && stristr(item->name,str))
))
|| (flag
&& (strcmp(item->jname,str) == 0
|| (battle_config.case_sensitive_aegisnames && strcmp(item->name,str) == 0)
|| (!battle_config.case_sensitive_aegisnames && strcasecmp(item->name,str) == 0)
))
) {
if( count < size )
data[count] = item;
++count;
if (
(flag == IT_SEARCH_NAME_PARTIAL
&& (stristr(itd->jname, str) != NULL
|| (battle_config.case_sensitive_aegisnames && strstr(itd->name, str))
|| (!battle_config.case_sensitive_aegisnames && stristr(itd->name, str))
))
|| (flag == IT_SEARCH_NAME_EXACT
&& (strcmp(itd->jname, str) == 0
|| (battle_config.case_sensitive_aegisnames && strcmp(itd->name, str) == 0)
|| (!battle_config.case_sensitive_aegisnames && strcasecmp(itd->name, str) == 0)
))
) {
if (length < size) {
data[length] = itd;
++length;
}

++results_count;
}
}

// search in the db
if( count < size )
{
struct DBData *db_data[MAX_SEARCH];
int db_count = 0;
size -= count;
db_count = itemdb->other->getall(itemdb->other, (struct DBData**)&db_data, size, itemdb->searchname_array_sub, str);
for (i = 0; i < db_count; i++)
data[count++] = DB->data2ptr(db_data[i]);
count += db_count;
// Search in dbmap
int dbmap_size = size - length;
if (dbmap_size > 0) {
struct DBData **dbmap_data = NULL;
int dbmap_count = 0;
CREATE(dbmap_data, struct DBData *, dbmap_size);

dbmap_count = itemdb->other->getall(itemdb->other, dbmap_data, dbmap_size, itemdb->searchname_array_sub, str, flag);
dbmap_size = min(dbmap_count, dbmap_size);

for (int i = 0; i < dbmap_size; ++i) {
data[length] = DB->data2ptr(dbmap_data[i]);
++length;
}

results_count += dbmap_count;
aFree(dbmap_data);
} else { // We got all matches we can return, so we only need to count now.
results_count += itemdb->other->getall(itemdb->other, NULL, 0, itemdb->searchname_array_sub, str, flag);
}
return count;

return results_count;
}

/* [Ind/Hercules] */
static int itemdb_chain_item(unsigned short chain_id, int *rate)
{
Expand Down
12 changes: 11 additions & 1 deletion src/map/itemdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,16 @@ enum ItemOptionTypes {
IT_OPT_MAX
};

/**
* Item name search flags
**/

enum item_name_search_flag {
IT_SEARCH_NAME_PARTIAL,
IT_SEARCH_NAME_EXACT,
IT_SEARCH_NAME_MAX,
};

/** Convenience item list (entry) used in various functions */
struct itemlist_entry {
int id; ///< Item ID or (inventory) index
Expand Down Expand Up @@ -633,7 +643,7 @@ struct itemdb_interface {
/* */
struct item_data* (*name2id) (const char *str);
struct item_data* (*search_name) (const char *name);
int (*search_name_array) (struct item_data** data, int size, const char *str, int flag);
int (*search_name_array) (struct item_data **data, const int size, const char *str, enum item_name_search_flag flag);
struct item_data* (*load)(int nameid);
struct item_data* (*search)(int nameid);
struct item_data* (*exists) (int nameid);
Expand Down
2 changes: 1 addition & 1 deletion src/map/script.c
Original file line number Diff line number Diff line change
Expand Up @@ -18804,7 +18804,7 @@ static BUILDIN(searchitem)
if ((items[0] = itemdb->exists(atoi(itemname)))) {
count = 1;
} else {
count = itemdb->search_name_array(items, ARRAYLENGTH(items), itemname, 0);
count = itemdb->search_name_array(items, ARRAYLENGTH(items), itemname, IT_SEARCH_NAME_PARTIAL);
if (count > MAX_SEARCH) count = MAX_SEARCH;
}

Expand Down