Преглед на файлове

- Rewrote the guild exp cache code to prevent overflows and to use the ers system.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@5937 54d463be-8e91-2dee-dedb-b68131a5f0ec
skotlex преди 19 години
родител
ревизия
8f34077a74
променени са 3 файла, в които са добавени 60 реда и са изтрити 41 реда
  1. 2 0
      Changelog-Trunk.txt
  2. 57 40
      src/map/guild.c
  3. 1 1
      src/map/guild.h

+ 2 - 0
Changelog-Trunk.txt

@@ -4,6 +4,8 @@ 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.
 
 2006/04/06
+	* Rewrote the guild exp cache code to prevent overflows and to use the
+	  entry reusage system. [Skotlex]
 	* The IRC Bot is now able to check each users access level prefix
 	  in the channel (~/&/@/%/+), the IRC command @kami now requires the
 	  user to be at least channel operator(@). Now I need to make it store

+ 57 - 40
src/map/guild.c

@@ -4,14 +4,17 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
+
+#include "../common/timer.h"
+#include "../common/nullpo.h"
+#include "../common/malloc.h"
+#include "../common/showmsg.h"
+#include "../common/ers.h"
 
 #include "map.h"
 #include "guild.h"
 #include "storage.h"
-#include "timer.h"
-#include "socket.h"
-#include "nullpo.h"
-#include "malloc.h"
 #include "battle.h"
 #include "npc.h"
 #include "pc.h"
@@ -20,7 +23,6 @@
 #include "intif.h"
 #include "clif.h"
 #include "skill.h"
-#include "showmsg.h"
 #include "log.h"
 
 static struct guild* guild_cache; //For fast retrieval of the same guild over and over. [Skotlex]
@@ -42,8 +44,10 @@ struct eventlist {
 
 // ギルドのEXPキャッシュ
 struct guild_expcache {
-	int guild_id, account_id, char_id, exp;
+	int guild_id, account_id, char_id;
+	unsigned int exp;
 };
+static struct eri *expcache_ers; //For handling of guild exp payment.
 
 struct{
 	int id;
@@ -200,7 +204,7 @@ void do_init_guild(void)
 {
 	guild_db=db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int));
 	castle_db=db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int));
-	guild_expcache_db=db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int));
+	guild_expcache_db=db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int));
 	guild_infoevent_db=db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int));
 	guild_castleinfoevent_db=db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int));
 
@@ -348,43 +352,36 @@ int guild_check_conflict(struct map_session_data *sd)
 // ギルドのEXPキャッシュをinter鯖にフラッシュする
 int guild_payexp_timer_sub(DBKey dataid, void *data, va_list ap)
 {
-	int i, *dellist, *delp;
+	int i;
 	struct guild_expcache *c;
 	struct guild *g;
-	double exp2;
 
 	c = (struct guild_expcache *)data;
-	dellist = va_arg(ap,int *);
-	delp = va_arg(ap,int *);
-
-	if (*delp >= GUILD_PAYEXP_LIST ||
+	
+	if (
 		(g = guild_search(c->guild_id)) == NULL ||
-		(i = guild_getindex(g, c->account_id, c->char_id)) < 0)
+		(i = guild_getindex(g, c->account_id, c->char_id)) < 0
+	) {
+		ers_free(expcache_ers, data);
 		return 0;
+	}
 
-	// It is *already* fixed... this would be more appropriate ^^; [celest]
-	exp2 = g->member[i].exp + c->exp;
-	g->member[i].exp = (exp2 > 0x7FFFFFFF) ? 0x7FFFFFFF : (int)exp2;
+	if (g->member[i].exp > INT_MAX - c->exp)
+		g->member[i].exp = INT_MAX;
+	else
+		g->member[i].exp+= c->exp;
 
-	//fixed a bug in exp overflow [Kevin]
-	//g->member[i].exp += c->exp;
-	//if(g->member[i].exp < 0)
-		//g->member[i].exp = 0x7FFFFFFF;
-	
 	intif_guild_change_memberinfo(g->guild_id,c->account_id,c->char_id,
 		GMI_EXP,&g->member[i].exp,sizeof(g->member[i].exp));
 	c->exp=0;
 
-	dellist[(*delp)++]=dataid.i;
+	ers_free(expcache_ers, data);
 	return 0;
 }
 
 int guild_payexp_timer(int tid, unsigned int tick, int id, int data)
 {
-	int dellist[GUILD_PAYEXP_LIST], delp = 0, i;
-	guild_expcache_db->foreach(guild_expcache_db, guild_payexp_timer_sub, dellist, &delp);
-	for (i = 0; i < delp; i++)
-		idb_remove(guild_expcache_db, dellist[i]);
+	guild_expcache_db->clear(guild_expcache_db,guild_payexp_timer_sub);
 	return 0;
 }
 
@@ -1116,18 +1113,22 @@ int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data)
 static void* create_expcache(DBKey key, va_list args) {
 	struct guild_expcache *c;
 	struct map_session_data *sd = va_arg(args, struct map_session_data*);
-	c = (struct guild_expcache *)aCallocA(1, sizeof(struct guild_expcache));
+
+	c = ers_alloc(expcache_ers, struct guild_expcache);
 	c->guild_id = sd->status.guild_id;
 	c->account_id = sd->status.account_id;
 	c->char_id = sd->status.char_id;
+	c->exp = 0;
 	return c;
 }
+
 // ギルドのEXP上納
-int guild_payexp(struct map_session_data *sd,int exp)
+unsigned int guild_payexp(struct map_session_data *sd,unsigned int exp)
 {
 	struct guild *g;
 	struct guild_expcache *c;
-	int per, exp2;
+	int per;
+	unsigned int exp2;
 	double tmp;
 	
 	nullpo_retr(0, sd);
@@ -1136,19 +1137,27 @@ int guild_payexp(struct map_session_data *sd,int exp)
 		(g = guild_search(sd->status.guild_id)) == NULL ||
 		(per = g->position[guild_getposition(sd,g)].exp_mode) <= 0)
 		return 0;
+	
 
 	if (per > 100) per = 100;
+	else
+	if (per < 1) return 0;
 
-	if ((exp2 = exp * per / 100) <= 0)
+	if ((tmp = exp * per / 100) <= 0)
 		return 0;
+	
+	exp2 = (unsigned int)tmp;
+	
+	if (battle_config.guild_exp_rate != 100)
+		tmp = tmp*battle_config.guild_exp_rate/100;
 
 	c = guild_expcache_db->ensure(guild_expcache_db, i2key(sd->status.char_id), create_expcache, sd);
-	tmp = c->exp;
-	if (battle_config.guild_exp_rate != 100)
-		tmp += battle_config.guild_exp_rate*exp2/100;
+
+	if (c->exp > UINT_MAX - (unsigned int)tmp)
+		c->exp = UINT_MAX;
 	else
-		tmp += exp2;
-	c->exp = (tmp > 0x7fffffff) ? 0x7fffffff : (int)tmp;
+		c->exp += (unsigned int)tmp;
+	
 	return exp2;
 }
 
@@ -1157,15 +1166,16 @@ int guild_getexp(struct map_session_data *sd,int exp)
 {
 	struct guild *g;
 	struct guild_expcache *c;
-	double tmp;
 	nullpo_retr(0, sd);
 
 	if (sd->status.guild_id == 0 || (g = guild_search(sd->status.guild_id)) == NULL)
 		return 0;
 
 	c = guild_expcache_db->ensure(guild_expcache_db, i2key(sd->status.char_id), create_expcache, sd);
-	tmp = c->exp + exp;
-	c->exp = (tmp > 0x7fffffff) ? 0x7fffffff : (int)tmp;
+	if (c->exp > UINT_MAX - exp)
+		c->exp = UINT_MAX;
+	else
+		c->exp += exp;
 	return exp;
 }
 
@@ -1975,11 +1985,18 @@ static int guild_infoevent_db_final(DBKey key,void *data,va_list ap)
 	aFree(data);
 	return 0;
 }
+
+static int guild_expcache_db_final(DBKey key,void *data,va_list ap)
+{
+	ers_free(expcache_ers, data);
+	return 0;
+}
+
 void do_final_guild(void)
 {
 	guild_db->destroy(guild_db,NULL);
 	castle_db->destroy(castle_db,NULL);
-	guild_expcache_db->destroy(guild_expcache_db,NULL);
+	guild_expcache_db->destroy(guild_expcache_db,guild_expcache_db_final);
 	guild_infoevent_db->destroy(guild_infoevent_db,guild_infoevent_db_final);
 	guild_castleinfoevent_db->destroy(guild_castleinfoevent_db,guild_infoevent_db_final);
 }

+ 1 - 1
src/map/guild.h

@@ -30,7 +30,7 @@ struct guild_castle *guild_mapindex2gc(short mapname);
 struct map_session_data *guild_getavailablesd(struct guild *g);
 int guild_getindex(struct guild *g,int account_id,int char_id);
 int guild_getposition(struct map_session_data *sd,struct guild *g);
-int guild_payexp(struct map_session_data *sd,int exp);
+unsigned int guild_payexp(struct map_session_data *sd,unsigned int exp);
 int guild_getexp(struct map_session_data *sd,int exp); // [Celest]
 
 int guild_create(struct map_session_data *sd,char *name);