From 42817756b603d2dc76c1408d0a6f432673350bd7 Mon Sep 17 00:00:00 2001 From: FlavioJS Date: Sun, 3 Feb 2008 19:20:42 +0000 Subject: * 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 --- src/map/map.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/map/map.h | 19 ++++++++ src/map/pc.h | 1 + 3 files changed, 168 insertions(+) (limited to 'src/map') 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) -- cgit v1.2.3-70-g09d2