Ver Fonte

* 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://svn.code.sf.net/p/rathena/svn/trunk@12170 54d463be-8e91-2dee-dedb-b68131a5f0ec

FlavioJS há 17 anos atrás
pai
commit
0594a1a350
5 ficheiros alterados com 180 adições e 0 exclusões
  1. 4 0
      Changelog-Trunk.txt
  2. 8 0
      src/common/db.h
  3. 148 0
      src/map/map.c
  4. 19 0
      src/map/map.h
  5. 1 0
      src/map/pc.h

+ 4 - 0
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

+ 8 - 0
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.                                       *

+ 148 - 0
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等の領域持ちのみ)
  *------------------------------------------*/

+ 19 - 0
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);

+ 1 - 0
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)