diff options
-rw-r--r-- | Changelog-Trunk.txt | 4 | ||||
-rw-r--r-- | configure | 4 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | src/map/itemdb.c | 245 |
4 files changed, 169 insertions, 86 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 835313a0f..7a48082c0 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -4,6 +4,10 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. 2007/09/21 + * itemdb.c/h using a static array of 32k struct item_data* entries (faster + itemdb loockup and a first step to remove map_session_data->inventory_data). + * Fixed a typo in the configure script that replaced CFLAGS with CPPFLAGS + when -Wno-pointer-sign is supported by the compiler. [FlavioJS] * Corrected skill Charge Attack as described in bugreport:67 [ultramage] - cast time is between 100% and 300% (+ infinite waiting fixed) - damage is also between 100% and 300% (doesn't increase past range 9) @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 11252 . +# From configure.in Revision: 11259 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61. # @@ -3748,7 +3748,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: checking whether $CC supports -Wno-pointer-sign" >&5 echo $ECHO_N "checking whether $CC supports -Wno-pointer-sign... $ECHO_C" >&6; } OLD_CFLAGS="$CFLAGS" -CFLAGS="$CPPFLAGS -Wno-pointer-sign" +CFLAGS="$CFLAGS -Wno-pointer-sign" cat >conftest.$ac_ext <<_ACEOF int foo; _ACEOF diff --git a/configure.in b/configure.in index 206de53f9..8e5cec894 100644 --- a/configure.in +++ b/configure.in @@ -133,7 +133,7 @@ AC_COMPILE_IFELSE( AC_MSG_CHECKING([whether $CC supports -Wno-pointer-sign]) OLD_CFLAGS="$CFLAGS" -CFLAGS="$CPPFLAGS -Wno-pointer-sign" +CFLAGS="$CFLAGS -Wno-pointer-sign" AC_COMPILE_IFELSE( [int foo;], [AC_MSG_RESULT([yes])], diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 4ed47df61..101738989 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -15,18 +15,25 @@ #include <stdlib.h> #include <string.h> +// 32k array entries (the rest goes to the db) +#define MAX_ITEMDB 0x8000 -static struct dbt* item_db; + + +static struct item_data* itemdb_array[MAX_ITEMDB]; +static struct dbt* itemdb_other; static struct item_group itemgroup_db[MAX_ITEMGROUP]; struct item_data dummy_item; //This is the default dummy item used for non-existant items. [Skotlex] + + /*========================================== * 名前で検索用 *------------------------------------------*/ // name = item alias, so we should find items aliases first. if not found then look for "jname" (full name) -int itemdb_searchname_sub(DBKey key,void *data,va_list ap) +static int itemdb_searchname_sub(DBKey key,void *data,va_list ap) { struct item_data *item=(struct item_data *)data,**dst,**dst2; char *str; @@ -52,9 +59,27 @@ int itemdb_searchname_sub(DBKey key,void *data,va_list ap) *------------------------------------------*/ struct item_data* itemdb_searchname(const char *str) { - struct item_data *item=NULL, *item2=NULL; + struct item_data* item; + struct item_data* item2=NULL; + int i; + + for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i ) + { + item = itemdb_array[i]; + if( item == NULL ) + continue; + + // Absolute priority to Aegis code name. + if( strcasecmp(item->name,str) == 0 ) + return item; + + //Second priority to Client displayed name. + if( strcasecmp(item->name,str) == 0 ) + item2 = item; + } - item_db->foreach(item_db,itemdb_searchname_sub,str,&item,&item2); + item = NULL; + itemdb_other->foreach(itemdb_other,itemdb_searchname_sub,str,&item,&item2); return item?item:item2; } @@ -77,7 +102,37 @@ static int itemdb_searchname_array_sub(DBKey key,void * data,va_list ap) *------------------------------------------*/ int itemdb_searchname_array(struct item_data** data, int size, const char *str) { - return item_db->getall(item_db,(void**)data,size,itemdb_searchname_array_sub,str); + struct item_data* item; + int i; + int count=0; + + // Search in the array + for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i ) + { + item = itemdb_array[i]; + if( item == NULL ) + continue; + + if( stristr(item->jname,str) || stristr(item->name,str) ) + { + if( count < size ) + data[count] = item; + ++count; + } + } + + // search in the db + if( count >= size ) + { + data = NULL; + size = 0; + } + else + { + data -= count; + size -= count; + } + return count + itemdb_other->getall(itemdb_other,(void**)data,size,itemdb_searchname_array_sub,str); } @@ -119,18 +174,18 @@ int itemdb_group_bonus(struct map_session_data* sd, int itemid) return bonus; } -/*========================================== - * DBの存在確認 - *------------------------------------------*/ +/// Searches for the item_data. +/// Returns the item_data or NULL if it does not exist. struct item_data* itemdb_exists(int nameid) { - struct item_data* id; - if (!nameid) return NULL; - id = idb_get(item_db,nameid); - //Adjust nameid in case it's used outside. [Skotlex] - if (id == &dummy_item) - dummy_item.nameid = nameid; - return id; + struct item_data* item; + + if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) ) + return itemdb_array[nameid]; + item = idb_get(itemdb_other,nameid); + if( item == &dummy_item ) + return NULL;// dummy data, doesn't exist + return item; } /*========================================== @@ -199,18 +254,18 @@ static void create_dummy_data(void) memset(&dummy_item, 0, sizeof(struct item_data)); dummy_item.nameid=500; dummy_item.weight=1; - dummy_item.value_sell = 1; - dummy_item.type=3; //Etc item - strncpy(dummy_item.name,"UNKNOWN_ITEM",ITEM_NAME_LENGTH-1); - strncpy(dummy_item.jname,"UNKNOWN_ITEM",ITEM_NAME_LENGTH-1); - dummy_item.view_id = UNKNOWN_ITEM_ID; + dummy_item.value_sell=1; + dummy_item.type=IT_ETC; //Etc item + safestrncpy(dummy_item.name,"UNKNOWN_ITEM",sizeof(dummy_item.name)); + safestrncpy(dummy_item.jname,"UNKNOWN_ITEM",sizeof(dummy_item.jname)); + dummy_item.view_id=UNKNOWN_ITEM_ID; } static void* create_item_data(DBKey key, va_list args) { struct item_data *id; - id=(struct item_data *)aCalloc(1,sizeof(struct item_data)); - id->nameid = key.i; + CREATE(id, struct item_data, 1); + id->nameid=key.i; id->weight=1; id->type=IT_ETC; return id; @@ -221,14 +276,26 @@ static void* create_item_data(DBKey key, va_list args) *------------------------------------------*/ struct item_data* itemdb_load(int nameid) { - struct item_data *id = idb_ensure(item_db,nameid,create_item_data); - if (id == &dummy_item) - { //Remove dummy_item, replace by real data. - DBKey key; + struct item_data *id; + DBKey key; + + if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) ) + { + id = itemdb_array[nameid]; + if( id == NULL ) + { + key.i = nameid; + id = itemdb_array[nameid] = create_item_data(key, NULL); + } + return id; + } + + id = idb_ensure(itemdb_other, nameid, create_item_data); + if( id == &dummy_item ) + {// Remove dummy_item, replace by real data. key.i = nameid; - idb_remove(item_db,nameid); id = create_item_data(key, NULL); - idb_put(item_db,nameid,id); + idb_put(itemdb_other, nameid, id); } return id; } @@ -246,7 +313,15 @@ static void* return_dummy_data(DBKey key, va_list args) *------------------------------------------*/ struct item_data* itemdb_search(int nameid) { - return idb_ensure(item_db,nameid,return_dummy_data); + if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) ) + { + DBKey key; + if( itemdb_array[nameid] ) + return itemdb_array[nameid]; + key.i = nameid; + return (struct item_data*)return_dummy_data(key, NULL); + } + return idb_ensure(itemdb_other,nameid,return_dummy_data); } /*========================================== @@ -630,18 +705,21 @@ static bool itemdb_parse_dbrow(char** str, char* source, int line) | id | name_english | name_japanese | type | price_buy | price_sell | weight | attack | defence | range | slots | equip_jobs | equip_upper | equip_genders | equip_locations | weapon_level | equip_level | refineable | view | script | equip_script | unequip_script | +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ */ - unsigned short nameid; + int nameid; struct item_data* id; nameid = atoi(str[0]); - if(nameid <= 0) + if( nameid <= 0 ) + { + ShowWarning("itemdb_parse_dbrow: Invalid id %d in line %d of \"%s\", skipping.\n", nameid, line, source); return false; - + } + //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Job Upper,Gender,Loc,wLV,eLV,refineable,View id = itemdb_load(nameid); - safestrncpy(id->name, str[1], ITEM_NAME_LENGTH-1); - safestrncpy(id->jname, str[2], ITEM_NAME_LENGTH-1); - + safestrncpy(id->name, str[1], sizeof(id->name)); + safestrncpy(id->jname, str[2], sizeof(id->jname)); + id->type = atoi(str[3]); if (id->type == IT_DELAYCONSUME) { //Items that are consumed only after target confirmation @@ -655,13 +733,13 @@ static bool itemdb_parse_dbrow(char** str, char* source, int line) if (id->value_buy < id->value_sell * 2) id->value_buy = id->value_sell * 2; // prevent exploit if (id->value_buy == 0 && id->value_sell > 0) id->value_buy = id->value_sell * 2; if (id->value_sell == 0 && id->value_buy > 0) id->value_sell = id->value_buy / 2; - + id->weight = atoi(str[6]); id->atk = atoi(str[7]); id->def = atoi(str[8]); id->range = atoi(str[9]); id->slot = atoi(str[10]); - + if (id->slot > MAX_SLOTS) { ShowWarning("itemdb_parse_dbrow: Item %d (%s) specifies %d slots, but the server only supports up to %d\n", nameid, id->jname, id->slot, MAX_SLOTS); @@ -672,18 +750,18 @@ static bool itemdb_parse_dbrow(char** str, char* source, int line) id->class_upper = atoi(str[12]); id->sex = atoi(str[13]); id->equip = atoi(str[14]); - + if (!id->equip && itemdb_isequip2(id)) { ShowWarning("Item %d (%s) is an equipment with no equip-field! Making it an etc item.\n", nameid, id->jname); id->type = IT_ETC; } - + id->wlv = atoi(str[15]); id->elv = atoi(str[16]); id->flag.no_refine = atoi(str[17]) ? 0 : 1; //FIXME: verify this id->look = atoi(str[18]); - + id->flag.available = 1; id->flag.value_notdc = 0; id->flag.value_notoc = 0; @@ -715,7 +793,7 @@ static int itemdb_readdb(void) char* filename[] = { "item_db.txt", "item_db2.txt" }; int fi; - for(fi = 0; fi < 2; fi++) + for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) { uint32 lines = 0, count = 0; char line[1024]; @@ -725,10 +803,10 @@ static int itemdb_readdb(void) sprintf(path, "%s/%s", db_path, filename[fi]); fp = fopen(path, "r"); - if(fp == NULL) { - if(fi > 0) - continue; - return -1; + if( fp == NULL ) + { + ShowWarning("itemdb_readdb: File not found \"%s\", skipping.\n", path); + continue; } // process rows one by one @@ -749,8 +827,9 @@ static int itemdb_readdb(void) } } - if (i < 19) { - ShowWarning("itemdb_readdb: Insufficient columns for item with id %d, skipping.\n", atoi(str[0])); + if( i < 19 ) + { + ShowWarning("itemdb_readdb: Insufficient columns in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); continue; } @@ -782,7 +861,7 @@ static int itemdb_readdb(void) continue; str[21] = p; //Unequip script, last column. - if (!itemdb_parse_dbrow(str, filename[fi], lines)) + if (!itemdb_parse_dbrow(str, path, lines)) continue; count++; @@ -879,30 +958,34 @@ static void itemdb_read(void) /*========================================== * Initialize / Finalize *------------------------------------------*/ -static int itemdb_final_sub (DBKey key,void *data,va_list ap) + +/// Destroys the item_data. +static void destroy_item_data(struct item_data* self, int free_self) +{ + if( self == NULL ) + return; + // free scripts + if( self->script ) + script_free_code(self->script); + if( self->equip_script ) + script_free_code(self->equip_script); + if( self->unequip_script ) + script_free_code(self->unequip_script); +#if defined(DEBUG) + // trash item + memset(self, 0xDD, sizeof(struct item_data)); +#endif + // free self + if( free_self ) + aFree(self); +} + +static int itemdb_final_sub(DBKey key,void *data,va_list ap) { - int flag; struct item_data *id = (struct item_data *)data; - flag = va_arg(ap, int); - if (id->script) - { - script_free_code(id->script); - id->script = NULL; - } - if (id->equip_script) - { - script_free_code(id->equip_script); - id->equip_script = NULL; - } - if (id->unequip_script) - { - script_free_code(id->unequip_script); - id->unequip_script = NULL; - } - // Whether to clear the item data (exception: do not clear the dummy item data - if (flag && id != &dummy_item) - aFree(id); + if( id != &dummy_item ) + destroy_item_data(id, 1); return 0; } @@ -915,24 +998,20 @@ void itemdb_reload(void) void do_final_itemdb(void) { - item_db->destroy(item_db, itemdb_final_sub, 1); - if (dummy_item.script) { - script_free_code(dummy_item.script); - dummy_item.script = NULL; - } - if (dummy_item.equip_script) { - script_free_code(dummy_item.equip_script); - dummy_item.equip_script = NULL; - } - if (dummy_item.unequip_script) { - script_free_code(dummy_item.unequip_script); - dummy_item.unequip_script = NULL; - } + int i; + + for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i ) + if( itemdb_array[i] ) + destroy_item_data(itemdb_array[i], 1); + + itemdb_other->destroy(itemdb_other, itemdb_final_sub); + destroy_item_data(&dummy_item, 0); } int do_init_itemdb(void) { - item_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int)); + memset(itemdb_array, 0, sizeof(itemdb_array)); + itemdb_other = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int)); create_dummy_data(); //Dummy data item. itemdb_read(); |