summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt2
-rw-r--r--src/map/guild.c97
-rw-r--r--src/map/guild.h2
3 files changed, 60 insertions, 41 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index dfa82f75b..ef52e2a11 100644
--- a/Changelog-Trunk.txt
+++ b/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
diff --git a/src/map/guild.c b/src/map/guild.c
index f2be83844..da579300f 100644
--- a/src/map/guild.c
+++ b/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);
}
diff --git a/src/map/guild.h b/src/map/guild.h
index d44500be5..697480136 100644
--- a/src/map/guild.h
+++ b/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);