From 7120b55ce40a6a0c4086da49d57c74baa72609d6 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Fri, 15 Nov 2013 23:05:55 -0200 Subject: Official expiration timer support As brought up in http://hercules.ws/board/topic/2225-paid-server/ Special Thanks to Haruna for all the help! Thanks to Beret, Ai4rei for information Signed-off-by: shennetsind --- src/map/clif.c | 2 +- src/map/map.c | 3 +++ src/map/pc.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- src/map/pc.h | 11 +++++++++ 4 files changed, 85 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/map/clif.c b/src/map/clif.c index f1a2ecf81..d84a0dea8 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -638,7 +638,7 @@ void clif_authrefuse(int fd, uint8 error_code) /// Notifies the client of a ban or forced disconnect (SC_NOTIFY_BAN). /// 0081 .B /// error code: -/// 0 = BAN_UNFAIR +/// 0 = BAN_UNFAIR -> "disconnected from server" -> MsgStringTable[3] /// 1 = server closed -> MsgStringTable[4] /// 2 = ID already logged in -> MsgStringTable[5] /// 3 = timeout/too much lag -> MsgStringTable[241] diff --git a/src/map/map.c b/src/map/map.c index 24fbeefa0..17648a661 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -1663,6 +1663,9 @@ int map_quit(struct map_session_data *sd) { //Non-active players should not have loaded any data yet (or it was cleared already) so no additional cleanups are needed. return 0; } + + if( sd->expiration_tid != INVALID_TIMER ) + timer->delete(sd->expiration_tid,pc->expiration_timer); if (sd->npc_timer_id != INVALID_TIMER) //Cancel the event timer. npc->timerevent_quit(sd); diff --git a/src/map/pc.c b/src/map/pc.c index 317e4e476..9cea5d424 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1049,6 +1049,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim sd->npc_timer_id = INVALID_TIMER; sd->pvp_timer = INVALID_TIMER; sd->fontcolor_tid = INVALID_TIMER; + sd->expiration_tid = INVALID_TIMER; /** * For the Secure NPC Timeout option (check config/Secure.h) [RR] **/ @@ -1176,11 +1177,8 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim clif->message(sd->fd, buf); } - // message of the limited time of the account - if (expiration_time != 0) { // don't display if it's unlimited or unknow value - char tmpstr[1024]; - strftime(tmpstr, sizeof(tmpstr) - 1, msg_txt(501), localtime(&expiration_time)); // "Your account time limit is: %d-%m-%Y %H:%M:%S." - clif->wis_message(sd->fd, map->wisp_server_name, tmpstr, strlen(tmpstr)+1); + if (expiration_time != 0) { + sd->expiration_time = expiration_time; } /** @@ -10300,6 +10298,65 @@ void pc_bank_withdraw(struct map_session_data *sd, int money) { void pc_scdata_received(struct map_session_data *sd) { pc->inventory_rentals(sd); clif->show_modifiers(sd); + + if (sd->expiration_time != 0) { // don't display if it's unlimited or unknow value + time_t exp_time = sd->expiration_time; + char tmpstr[1024]; + strftime(tmpstr, sizeof(tmpstr) - 1, msg_txt(501), localtime(&exp_time)); // "Your account time limit is: %d-%m-%Y %H:%M:%S." + clif->wis_message(sd->fd, map->wisp_server_name, tmpstr, strlen(tmpstr)+1); + + pc->expire_check(sd); + } +} +int pc_expiration_timer(int tid, int64 tick, int id, intptr_t data) { + struct map_session_data *sd = map->id2sd(id); + + if( !sd ) return 0; + + sd->expiration_tid = INVALID_TIMER; + + if( sd->fd ) + clif->authfail_fd(sd->fd,10); + + map->quit(sd); + + return 0; +} +/* this timer exists only when a character with a expire timer > 24h is online */ +/* it loops thru online players once an hour to check whether a new < 24h is available */ +int pc_global_expiration_timer(int tid, int64 tick, int id, intptr_t data) { + struct s_mapiterator* iter; + struct map_session_data* sd; + + iter = mapit_getallusers(); + + for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) { + if( sd->expiration_time ) + pc->expire_check(sd); + } + + mapit->free(iter); + + return 0; +} +void pc_expire_check(struct map_session_data *sd) { + /* ongoing timer */ + if( sd->expiration_tid != INVALID_TIMER ) + return; + + /* not within the next 24h, enable the global check */ + if( sd->expiration_time > ( time(NULL) + ( ( 60 * 60 ) * 24 ) ) ) { + + /* global check not running, enable */ + if( pc->expiration_tid == INVALID_TIMER ) { + /* starts in 1h, repeats every hour */ + pc->expiration_tid = timer->add_interval(timer->gettick() + ((1000*60)*60), pc->global_expiration_timer, 0, 0, ((1000*60)*60)); + } + + return; + } + + sd->expiration_tid = timer->add(timer->gettick() + (int64)(sd->expiration_time - time(NULL))*1000, pc->expiration_timer, sd->bl.id, 0); } /*========================================== @@ -10332,6 +10389,8 @@ void do_init_pc(bool minimal) { timer->add_func_list(pc->follow_timer, "pc_follow_timer"); timer->add_func_list(pc->endautobonus, "pc_endautobonus"); timer->add_func_list(pc->charm_timer, "pc_charm_timer"); + timer->add_func_list(pc->global_expiration_timer,"pc_global_expiration_timer"); + timer->add_func_list(pc->expiration_timer,"pc_expiration_timer"); timer->add(timer->gettick() + map->autosave_interval, pc->autosave, 0, 0); @@ -10393,6 +10452,8 @@ void pc_defaults(void) { memcpy(pc->sg_info, sg_info, sizeof(pc->sg_info)); /* */ pc->sc_display_ers = NULL; + /* */ + pc->expiration_tid = INVALID_TIMER; /* funcs */ pc->init = do_init_pc; pc->final = do_final_pc; @@ -10636,4 +10697,8 @@ void pc_defaults(void) { pc->scdata_received = pc_scdata_received; pc->bound_clear = pc_bound_clear; + + pc->expiration_timer = pc_expiration_timer; + pc->global_expiration_timer = pc_global_expiration_timer; + pc->expire_check = pc_expire_check; } diff --git a/src/map/pc.h b/src/map/pc.h index 32ca214c0..71c76b643 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -518,9 +518,14 @@ struct map_session_data { unsigned char delayed_damage;//ref. counter bugreport:7307 [Ind/Hercules] + /* HPM Custom Struct */ struct HPluginData **hdata; unsigned int hdatac; + /* expiration_time timer id */ + int expiration_tid; + time_t expiration_time; + /* */ struct { unsigned int second,third; @@ -741,6 +746,8 @@ struct pc_interface { struct sg_data sg_info[MAX_PC_FEELHATE]; /* */ struct eri *sc_display_ers; + /* global expiration timer id */ + int expiration_tid; /* funcs */ void (*init) (bool minimal); void (*final) (void); @@ -985,6 +992,10 @@ struct pc_interface { void (*scdata_received) (struct map_session_data *sd); void (*bound_clear) (struct map_session_data *sd, enum e_item_bound_type type); + + int (*expiration_timer) (int tid, int64 tick, int id, intptr_t data); + int (*global_expiration_timer) (int tid, int64 tick, int id, intptr_t data); + void (*expire_check) (struct map_session_data *sd); }; struct pc_interface *pc; -- cgit v1.2.3-60-g2f50