diff options
author | FlavioJS <FlavioJS@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2008-02-03 19:20:42 +0000 |
---|---|---|
committer | FlavioJS <FlavioJS@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2008-02-03 19:20:42 +0000 |
commit | 42817756b603d2dc76c1408d0a6f432673350bd7 (patch) | |
tree | b9e0780f47c550e7bce922bc84de0941beee9a93 | |
parent | f010f32adb51f7d4d2648abd475a900ecf07bafa (diff) | |
download | hercules-42817756b603d2dc76c1408d0a6f432673350bd7.tar.gz hercules-42817756b603d2dc76c1408d0a6f432673350bd7.tar.bz2 hercules-42817756b603d2dc76c1408d0a6f432673350bd7.tar.xz hercules-42817756b603d2dc76c1408d0a6f432673350bd7.zip |
* Added an iterator to map.h/c.
Will be used instead of map_getallusers, which has problems with dangling pointers (returned array isn't updated).
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@12170 54d463be-8e91-2dee-dedb-b68131a5f0ec
-rw-r--r-- | Changelog-Trunk.txt | 4 | ||||
-rw-r--r-- | src/common/db.h | 8 | ||||
-rw-r--r-- | src/map/map.c | 148 | ||||
-rw-r--r-- | src/map/map.h | 19 | ||||
-rw-r--r-- | src/map/pc.h | 1 |
5 files changed, 180 insertions, 0 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 19854d755..23b19ff8b 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -3,6 +3,10 @@ Date Added AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK. IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. +2008/02/03 + * Added an iterator to map.h/c. [FlavioJS] + Will be used instead of map_getallusers, which has problems with + dangling pointers (returned array isn't updated). 2008/02/01 * Fixed sql charserver crashing sometimes (bugreport:870) [ultramage] 2008/01/29 diff --git a/src/common/db.h b/src/common/db.h index cf9e4e82e..eb6318869 100644 --- a/src/common/db.h +++ b/src/common/db.h @@ -608,6 +608,14 @@ struct DBMap { #define strdb_alloc(opt,maxlen) db_alloc(__FILE__,__LINE__,DB_STRING,(opt),(maxlen)) #define stridb_alloc(opt,maxlen) db_alloc(__FILE__,__LINE__,DB_ISTRING,(opt),(maxlen)) #define db_destroy(db) ( (db)->destroy((db),NULL) ) +// Other macros +#define db_iterator(db) ( (db)->iterator(db) ) +#define dbi_first(dbi) ( (dbi)->first(dbi,NULL) ) +#define dbi_last(dbi) ( (dbi)->last(dbi,NULL) ) +#define dbi_next(dbi) ( (dbi)->next(dbi,NULL) ) +#define dbi_prev(dbi) ( (dbi)->prev(dbi,NULL) ) +#define dbi_exists(dbi) ( (dbi)->exists(dbi) ) +#define dbi_destroy(dbi) ( (dbi)->destroy(dbi) ) /*****************************************************************************\ * (2) Section with public functions. * diff --git a/src/map/map.c b/src/map/map.c index bd12e418b..cda1fccc9 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -1829,6 +1829,154 @@ int map_foreachiddb(int (*func)(DBKey,void*,va_list),...) return 0; } +/// Iterator. +/// Can filter by bl type. +struct s_mapiterator +{ + enum e_mapitflags flags;// flags for special behaviour + enum bl_type types;// what bl types to return + DBIterator* dbi;// database iterator +}; + +/// Returns true if the block_list matches the description in the iterator. +/// +/// @param _mapit_ Iterator +/// @param _bl_ block_list +/// @return true if it matches +#define MAPIT_MATCHES(_mapit_,_bl_) \ + ( \ + ( (_bl_)->type & (_mapit_)->types /* type matches */ ) && \ + ( (_bl_)->type != BL_PC /* not a pc */ || !((_mapit_)->flags & MAPIT_PCISPLAYING) /* any pc state */ || pc_isplaying((TBL_PC*)(_bl_)) /* pc is playing */ ) \ + ) + +/// Allocates a new iterator. +/// Returns the new iterator. +/// types can represent several BL's as a bit field. +/// TODO should this be expanded to allow filtering of map/guild/party/chat/cell/area/...? +/// +/// @param flags Flags of the iterator +/// @param type Target types +/// @return Iterator +struct s_mapiterator* mapit_alloc(enum e_mapitflags flags, enum bl_type types) +{ + struct s_mapiterator* mapit; + + CREATE(mapit, struct s_mapiterator, 1); + if( !(types & BL_PC) && (flags & MAPIT_PCISPLAYING) ) flags ^= MAPIT_PCISPLAYING;// incompatible flag + mapit->flags = flags; + mapit->types = types; + if( types == BL_PC ) mapit->dbi = db_iterator(pc_db); + else if( types == BL_MOB ) mapit->dbi = db_iterator(mobid_db); + else mapit->dbi = db_iterator(id_db); + return mapit; +} + +/// Frees the iterator. +/// +/// @param mapit Iterator +void mapit_free(struct s_mapiterator* mapit) +{ + nullpo_retv(mapit); + + dbi_destroy(mapit->dbi); + aFree(mapit); +} + +/// Returns the first block_list that matches the description. +/// Returns NULL if not found. +/// +/// @param mapit Iterator +/// @return first block_list or NULL +struct block_list* mapit_first(struct s_mapiterator* mapit) +{ + struct block_list* bl; + + nullpo_retr(NULL,mapit); + + for( bl = (struct block_list*)dbi_first(mapit->dbi); bl != NULL; bl = (struct block_list*)dbi_next(mapit->dbi) ) + { + if( MAPIT_MATCHES(mapit,bl) ) + break;// found match + } + return bl; +} + +/// Returns the last block_list that matches the description. +/// Returns NULL if not found. +/// +/// @param mapit Iterator +/// @return last block_list or NULL +struct block_list* mapit_last(struct s_mapiterator* mapit) +{ + struct block_list* bl; + + nullpo_retr(NULL,mapit); + + for( bl = (struct block_list*)dbi_last(mapit->dbi); bl != NULL; bl = (struct block_list*)dbi_prev(mapit->dbi) ) + { + if( MAPIT_MATCHES(mapit,bl) ) + break;// found match + } + return bl; +} + +/// Returns the next block_list that matches the description. +/// Returns NULL if not found. +/// +/// @param mapit Iterator +/// @return next block_list or NULL +struct block_list* mapit_next(struct s_mapiterator* mapit) +{ + struct block_list* bl; + + nullpo_retr(NULL,mapit); + + for( ; ; ) + { + bl = (struct block_list*)dbi_next(mapit->dbi); + if( bl == NULL ) + break;// end + if( MAPIT_MATCHES(mapit,bl) ) + break;// found a match + // try next + } + return bl; +} + +/// Returns the previous block_list that matches the description. +/// Returns NULL if not found. +/// +/// @param mapit Iterator +/// @return previous block_list or NULL +struct block_list* mapit_prev(struct s_mapiterator* mapit) +{ + struct block_list* bl; + + nullpo_retr(NULL,mapit); + + for( ; ; ) + { + bl = (struct block_list*)dbi_prev(mapit->dbi); + if( bl == NULL ) + break;// end + if( MAPIT_MATCHES(mapit,bl) ) + break;// found a match + // try prev + } + return bl; +} + +/// Returns true if the current block_list exists in the database. +/// +/// @param mapit Iterator +/// @return true if it exists +bool mapit_exists(struct s_mapiterator* mapit) +{ + nullpo_retr(false,mapit); + + return dbi_exists(mapit->dbi); +} + /*========================================== * map.npcへ追加 (warp等の領域持ちのみ) *------------------------------------------*/ diff --git a/src/map/map.h b/src/map/map.h index 436fbca33..81b83257c 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -1324,6 +1324,25 @@ void map_foreachmob(int (*func)(DBKey,void*,va_list),...); int map_foreachiddb(int (*)(DBKey,void*,va_list),...); struct map_session_data * map_nick2sd(const char*); +/// Bitfield of flags for the iterator. +enum e_mapitflags +{ + MAPIT_NORMAL = 0, + MAPIT_PCISPLAYING = 1,// player is authed, not waiting disconnect and not in final save +}; +struct s_mapiterator; +struct s_mapiterator* mapit_alloc(enum e_mapitflags flags, enum bl_type types); +void mapit_free(struct s_mapiterator* mapit); +struct block_list* mapit_first(struct s_mapiterator* mapit); +struct block_list* mapit_last(struct s_mapiterator* mapit); +struct block_list* mapit_next(struct s_mapiterator* mapit); +struct block_list* mapit_prev(struct s_mapiterator* mapit); +bool mapit_exists(struct s_mapiterator* mapit); +#define mapit_getallusers() mapit_alloc(MAPIT_PCISPLAYING,BL_PC) +#define mapit_geteachpc() mapit_alloc(MAPIT_NORMAL,BL_PC) +#define mapit_geteachmob() mapit_alloc(MAPIT_NORMAL,BL_MOB) +#define mapit_geteachiddb() mapit_alloc(MAPIT_NORMAL,BL_ALL) + // その他 int map_check_dir(int s_dir,int t_dir); unsigned char map_calc_dir( struct block_list *src,int x,int y); diff --git a/src/map/pc.h b/src/map/pc.h index d179ec770..e9f300d9c 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -126,6 +126,7 @@ extern int duel_count; #define pc_is50overweight(sd) ( (sd)->weight*100 >= (sd)->max_weight*battle_config.natural_heal_weight_rate ) #define pc_is90overweight(sd) ( (sd)->weight*10 >= (sd)->max_weight*9 ) #define pc_maxparameter(sd) ( (sd)->class_&JOBL_BABY ? battle_config.max_baby_parameter : battle_config.max_parameter ) +#define pc_isplaying(sd) ( (sd)->state.auth /* is authed */ && !(sd)->state.waitingdisconnect /* not waiting disconnect */ && !(sd)->state.finalsave /* not in final save */ ) #define pc_stop_walking(sd, type) unit_stop_walking(&(sd)->bl, type) #define pc_stop_attack(sd) unit_stop_attack(&(sd)->bl) |