Resolved a potential map-server crash

* Fixes #1839, fixes #1844, and fixes #1882.
* Resolves players at login attempting to calculate their statuses who haven't been fully loaded.
* Added a new state flag to make sure inventory and status data is loaded before player's statuses are calculated.
Thanks to @Tokeiburu, @Everade, and @MrAntares!
This commit is contained in:
aleos 2017-01-22 13:03:27 -05:00
parent c6470ff4ff
commit 7543f1cba7
3 changed files with 12 additions and 4 deletions

View File

@ -10062,8 +10062,9 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
if(sd->bl.prev != NULL) if(sd->bl.prev != NULL)
return; return;
if (!sd->state.active) { //Character loading is not complete yet! // Autotraders should ignore this entirely, clif_parse_LoadEndAck is always invoked manually for them
//Let pc_reg_received reinvoke this when ready. if (!sd->state.active || (!sd->state.autotrade && !sd->state.pc_loaded)) { //Character loading is not complete yet!
//Let pc_reg_received or intif_parse_StorageReceived reinvoke this when ready.
sd->state.connect_new = 0; sd->state.connect_new = 0;
return; return;
} }

View File

@ -1103,8 +1103,6 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_
sd->status.body = cap_value(sd->status.body,MIN_BODY_STYLE,MAX_BODY_STYLE); sd->status.body = cap_value(sd->status.body,MIN_BODY_STYLE,MAX_BODY_STYLE);
//Initializations to null/0 unneeded since map_session_data was filled with 0 upon allocation. //Initializations to null/0 unneeded since map_session_data was filled with 0 upon allocation.
if (!sd->status.hp)
pc_setdead(sd);
sd->state.connect_new = 1; sd->state.connect_new = 1;
sd->followtimer = INVALID_TIMER; // [MouseJstr] sd->followtimer = INVALID_TIMER; // [MouseJstr]
@ -1405,6 +1403,7 @@ void pc_reg_received(struct map_session_data *sd)
if (sd->state.active) if (sd->state.active)
return; return;
sd->state.active = 1; sd->state.active = 1;
sd->state.pc_loaded = false; // Ensure inventory data and status data is loaded before we calculate player stats
intif_storage_request(sd,TABLE_STORAGE, 0, STOR_MODE_ALL); // Request storage data intif_storage_request(sd,TABLE_STORAGE, 0, STOR_MODE_ALL); // Request storage data
intif_storage_request(sd,TABLE_CART, 0, STOR_MODE_ALL); // Request cart data intif_storage_request(sd,TABLE_CART, 0, STOR_MODE_ALL); // Request cart data
@ -11464,6 +11463,13 @@ void pc_damage_log_clear(struct map_session_data *sd, int id)
void pc_scdata_received(struct map_session_data *sd) { void pc_scdata_received(struct map_session_data *sd) {
pc_inventory_rentals(sd); // Needed here to remove rentals that have Status Changes after chrif_load_scdata has finished pc_inventory_rentals(sd); // Needed here to remove rentals that have Status Changes after chrif_load_scdata has finished
sd->state.pc_loaded = true;
if (sd->state.connect_new == 0 && sd->fd) { // Character already loaded map! Gotta trigger LoadEndAck manually.
sd->state.connect_new = 1;
clif_parse_LoadEndAck(sd->fd, sd);
}
if (pc_iscarton(sd)) { if (pc_iscarton(sd)) {
sd->cart_weight_max = 0; // Force a client refesh sd->cart_weight_max = 0; // Force a client refesh
status_calc_cart_weight(sd, CALCWT_ITEM|CALCWT_MAXBONUS|CALCWT_CARTSTATE); status_calc_cart_weight(sd, CALCWT_ITEM|CALCWT_MAXBONUS|CALCWT_CARTSTATE);

View File

@ -259,6 +259,7 @@ struct map_session_data {
uint8 isBoundTrading; // Player is currently add bound item to trade list [Cydh] uint8 isBoundTrading; // Player is currently add bound item to trade list [Cydh]
bool ignoretimeout; // Prevent the SECURE_NPCTIMEOUT function from closing current script. bool ignoretimeout; // Prevent the SECURE_NPCTIMEOUT function from closing current script.
unsigned int workinprogress : 2; // See clif.h::e_workinprogress unsigned int workinprogress : 2; // See clif.h::e_workinprogress
bool pc_loaded; // Ensure inventory data and status data is loaded before we calculate player stats
} state; } state;
struct { struct {
unsigned char no_weapon_damage, no_magic_damage, no_misc_damage; unsigned char no_weapon_damage, no_magic_damage, no_misc_damage;