summaryrefslogtreecommitdiff
path: root/src/map/map.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/map.c')
-rw-r--r--src/map/map.c196
1 files changed, 61 insertions, 135 deletions
diff --git a/src/map/map.c b/src/map/map.c
index c02a896a9..78e67d3d4 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -102,7 +102,6 @@ static DBMap* mobid_db=NULL; // int id -> struct mob_data*
static DBMap* map_db=NULL; // unsigned int mapindex -> struct map_data*
static DBMap* nick_db=NULL; // int char_id -> struct charid2nick* (requested names of offline characters)
static DBMap* charid_db=NULL; // int char_id -> struct map_session_data*
-static DBMap* quit_db=NULL; // int account_id -> struct map_session_data* (players that are quitting or changing map-server)
static int map_users=0;
static struct block_list *objects[MAX_FLOORITEM];
@@ -1540,117 +1539,76 @@ void map_deliddb(struct block_list *bl)
idb_remove(id_db,bl->id);
}
-/// Returns true if the map server knows the account (to reject logins).
-bool map_knowsaccount(int account_id)
-{
- return (map_id2sd(account_id) || idb_get(quit_db,account_id) ? true : false);
-}
-
/*==========================================
- * PCのquit?理 map.c?分
- *
- * quit?理の主?が違うような?もしてきた
+ * Standard call when a player connection is closed.
*------------------------------------------*/
int map_quit(struct map_session_data *sd)
{
- struct map_session_data* sd2;
- if(!sd->state.auth) { //Removing a player that hasn't even finished loading
- TBL_PC *sd2 = map_id2sd(sd->status.account_id);
- if (sd->pd) unit_free(&sd->pd->bl,-1);
- if (sd->hd) unit_free(&sd->hd->bl,-1);
- //Double login, let original do the cleanups below.
- if (sd2 && sd2 != sd)
- return 0;
- map_deliddb(&sd->bl);
+ if(!sd->state.active) { //Removing a player that is not active.
+ struct auth_node *node = chrif_search(sd->status.account_id);
+ if (node && node->char_id == sd->status.char_id &&
+ node->state != ST_LOGOUT)
+ //Except when logging out, clear the auth-connect data immediately.
+ chrif_auth_delete(node->account_id, node->char_id, node->state);
+ //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->state.waitingdisconnect) {
- if (sd->npc_timer_id != -1) //Cancel the event timer.
- npc_timerevent_quit(sd);
-
- npc_script_event(sd, NPCE_LOGOUT);
- sd->state.waitingdisconnect = 1;
- if (sd->pd) unit_free(&sd->pd->bl,0);
- if (sd->hd) unit_free(&sd->hd->bl,0);
- unit_free(&sd->bl,3);
- chrif_save(sd,1);
- } else { //Try to free some data, without saving anything (this could be invoked on map server change. [Skotlex]
- if (sd->bl.prev != NULL)
- unit_remove_map(&sd->bl, 0);
- if (sd->pd && sd->pd->bl.prev != NULL)
- unit_remove_map(&sd->pd->bl, 0);
- if (sd->hd && sd->hd->bl.prev != NULL)
- unit_remove_map(&sd->hd->bl, 0);
- }
-
- map_deliddb(&sd->bl);
- if( (sd2=(struct map_session_data*)idb_put(quit_db, sd->status.account_id, sd)) )
- {
- ShowDebug("map_quit: Possible double login AID/CID: %d/%d AID/CID: %d/%d\n", sd2->status.account_id, sd2->status.char_id, sd->status.account_id, sd->status.char_id);
- aFree(sd2);
- }
- if(sd->reg)
- { //Double logout already freed pointer fix... [Skotlex]
- aFree(sd->reg);
- sd->reg = NULL;
- sd->reg_num = 0;
- }
- if(sd->regstr)
- {
- int i;
- for( i = 0; i < sd->regstr_num; ++i )
- if( sd->regstr[i].data )
- aFree(sd->regstr[i].data);
- aFree(sd->regstr);
- sd->regstr = NULL;
- sd->regstr_num = 0;
- }
- if (sd->st) {
- if (sd->st->stack)
- script_free_stack (sd->st->stack);
- aFree(sd->st);
- sd->st = NULL;
- sd->npc_id = 0;
- }
- if(sd->fd)
- { //Player will be free'd on save-ack. [Skotlex]
- if (session[sd->fd])
- session[sd->fd]->session_data = NULL;
- sd->fd = 0;
- }
- return 0;
-}
-
-void map_quit_ack(int account_id, int char_id)
-{
- struct map_session_data* sd = (struct map_session_data*)idb_get(quit_db,account_id);
- if( sd )
- {
- if( sd->status.char_id != char_id )
- ShowDebug("map_quit_ack: Possible double login AID/CID: %d/%d AID/CID: %d/%d\n", account_id, char_id, sd->status.account_id, sd->status.char_id);
- else
- idb_remove(quit_db,account_id);
- }
-}
-
-static int do_reconnect_map_sub(DBKey key,void *data,va_list va)
-{
- struct map_session_data *sd = (TBL_PC*)data;
- if (sd->state.finalsave) {
- sd->state.finalsave = 0;
- chrif_save(sd, 1); //Resend to save!
- return 1;
+ if (sd->npc_timer_id != -1) //Cancel the event timer.
+ npc_timerevent_quit(sd);
+
+ npc_script_event(sd, NPCE_LOGOUT);
+
+ //Unit_free handles clearing the player related data,
+ //map_quit handles extra specific data which is related to quitting normally
+ //(changing map-servers invokes unit_free but bypasses map_quit)
+ if(sd->sc.count) {
+ //Status that are not saved...
+ if(sd->sc.data[SC_SPURT])
+ status_change_end(&sd->bl,SC_SPURT,-1);
+ if(sd->sc.data[SC_BERSERK])
+ status_change_end(&sd->bl,SC_BERSERK,-1);
+ if(sd->sc.data[SC_TRICKDEAD])
+ status_change_end(&sd->bl,SC_TRICKDEAD,-1);
+ if(sd->sc.data[SC_GUILDAURA])
+ status_change_end(&sd->bl,SC_GUILDAURA,-1);
+ if (battle_config.debuff_on_logout&1) {
+ if(sd->sc.data[SC_ORCISH])
+ status_change_end(&sd->bl,SC_ORCISH,-1);
+ if(sd->sc.data[SC_STRIPWEAPON])
+ status_change_end(&sd->bl,SC_STRIPWEAPON,-1);
+ if(sd->sc.data[SC_STRIPARMOR])
+ status_change_end(&sd->bl,SC_STRIPARMOR,-1);
+ if(sd->sc.data[SC_STRIPSHIELD])
+ status_change_end(&sd->bl,SC_STRIPSHIELD,-1);
+ if(sd->sc.data[SC_STRIPHELM])
+ status_change_end(&sd->bl,SC_STRIPHELM,-1);
+ if(sd->sc.data[SC_EXTREMITYFIST])
+ status_change_end(&sd->bl,SC_EXTREMITYFIST,-1);
+ if(sd->sc.data[SC_EXPLOSIONSPIRITS])
+ status_change_end(&sd->bl,SC_EXPLOSIONSPIRITS,-1);
+ if(sd->sc.data[SC_REGENERATION] && sd->sc.data[SC_REGENERATION]->val4)
+ status_change_end(&sd->bl,SC_REGENERATION,-1);
+ }
+ if (battle_config.debuff_on_logout&2)
+ {
+ if(sd->sc.data[SC_MAXIMIZEPOWER])
+ status_change_end(&sd->bl,SC_MAXIMIZEPOWER,-1);
+ if(sd->sc.data[SC_MAXOVERTHRUST])
+ status_change_end(&sd->bl,SC_MAXOVERTHRUST,-1);
+ if(sd->sc.data[SC_STEELBODY])
+ status_change_end(&sd->bl,SC_STEELBODY,-1);
+ }
}
+
+ unit_remove_map_pc(sd,3);
+ pc_makesavestatus(sd);
+ pc_clean_skilltree(sd);
+ chrif_save(sd,1);
+ unit_free_pc(sd);
return 0;
}
-void do_reconnect_map(void)
-{
- pc_db->foreach(pc_db,do_reconnect_map_sub);
- pc_db->foreach(quit_db,do_reconnect_map_sub);//## FIXME possible loss of data [FlavioJS]
-}
-
/*==========================================
* id番?のPCを探す。居なければNULL
*------------------------------------------*/
@@ -1765,15 +1723,6 @@ struct block_list * map_id2bl(int id)
return bl;
}
-static int map_getallpc_sub(DBKey key,void * data,va_list ap)
-{
- struct map_session_data *sd = (struct map_session_data*) data;
- if (!sd->state.auth || sd->state.waitingdisconnect || sd->state.finalsave)
- return 1; //Do not count in not-yet authenticated characters or ready to disconnect ones.
-
- return 0;
-}
-
/*==========================================
* Returns an array of all players in the server (includes non connected ones) [Skotlex]
* The int pointer given returns the count of elements in the array.
@@ -1805,7 +1754,7 @@ struct map_session_data** map_getallusers(int *users)
RECREATE(all_sd, struct map_session_data*, all_count);
}
- *users = pc_db->getall(pc_db,(void**)all_sd,all_count,map_getallpc_sub);
+ *users = pc_db->getall(pc_db,(void**)all_sd,all_count,NULL);
if (*users > (signed int)all_count) //Which should be impossible...
*users = all_count;
@@ -1857,8 +1806,7 @@ struct s_mapiterator
/// @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 */ ) \
+ ( (_bl_)->type & (_mapit_)->types /* type matches */ ) \
)
/// Allocates a new iterator.
@@ -1874,7 +1822,6 @@ 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);
@@ -3127,19 +3074,6 @@ static int cleanup_db_sub(DBKey key,void *data,va_list va)
return cleanup_sub((struct block_list*)data, NULL);
}
-static int cleanup_db_subpc(DBKey key,void *data,va_list va)
-{
- struct map_session_data *sd = (TBL_PC*)data;
- if (!sd->state.finalsave)
- { //Error?
- ShowError("do_final: Player character in DB which was not sent to save! %d:%d\n", sd->status.account_id, sd->status.char_id);
- map_quit(sd); //Attempt force-save
- }
- //Force remove from memory...
- map_quit_ack(sd->status.account_id, sd->status.char_id);
- return 1;
-}
-
/*==========================================
* map鯖終了・理
*------------------------------------------*/
@@ -3164,9 +3098,6 @@ void do_final(void)
id_db->foreach(id_db,cleanup_db_sub);
chrif_char_reset_offline();
chrif_flush_fifo();
- //Online players were sent to save, but the ack will not arrive on time!
- //They have to be removed from memory, and assume the char-server saved them.
- pc_db->foreach(pc_db,cleanup_db_subpc);
do_final_atcommand();
do_final_battle();
@@ -3210,7 +3141,6 @@ void do_final(void)
mobid_db->destroy(mobid_db, NULL);
nick_db->destroy(nick_db, nick_db_final);
charid_db->destroy(charid_db, NULL);
- db_destroy(quit_db);
#ifndef TXT_ONLY
map_sql_close();
@@ -3222,9 +3152,6 @@ static int map_abort_sub(DBKey key,void * data,va_list ap)
{
struct map_session_data *sd = (TBL_PC*)data;
- if (!sd->state.auth || sd->state.waitingdisconnect || sd->state.finalsave)
- return 0;
-
chrif_save(sd,1);
return 1;
}
@@ -3389,7 +3316,6 @@ int do_init(int argc, char *argv[])
map_db = uidb_alloc(DB_OPT_BASE);
nick_db = idb_alloc(DB_OPT_BASE);
charid_db = idb_alloc(DB_OPT_BASE);
- quit_db = idb_alloc(DB_OPT_RELEASE_DATA);
#ifndef TXT_ONLY
map_sql_init();
#endif /* not TXT_ONLY */