From 4ff67a9c9977e216c5b63bf5c80480dba1e2fcab Mon Sep 17 00:00:00 2001 From: shennetsind Date: Mon, 24 Jun 2013 13:13:27 -0300 Subject: Fixed Bug #7412 Special Thanks to shenhuyong http://hercules.ws/board/tracker/issue-7412-create-instancereloadscript-causes-map-server-crash/ Signed-off-by: shennetsind --- src/common/mmo.h | 2 +- src/map/instance.c | 45 ++++++++++++++++++++++++++------------------- src/map/map.c | 3 +-- src/map/npc.c | 6 ++++-- src/map/party.c | 36 ++++++++++++++++++++++-------------- src/map/party.h | 2 +- src/map/pc.c | 24 +++++++++++++++--------- src/map/pc.h | 2 +- src/map/script.c | 24 +++++++++++++++--------- 9 files changed, 86 insertions(+), 58 deletions(-) diff --git a/src/common/mmo.h b/src/common/mmo.h index 8643d2b54..6e5dae099 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -534,7 +534,7 @@ struct guild { /* TODO: still used for something?|: */ unsigned short save_flag; // for TXT saving - unsigned short *instance; + short *instance; unsigned short instances; void *channel; diff --git a/src/map/instance.c b/src/map/instance.c index 690f14cfe..6b80f5d75 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -46,10 +46,11 @@ bool instance_is_valid(int instance_id) { * On success return instance_id *--------------------------------------*/ int instance_create(int owner_id, const char *name, enum instance_owner_type type) { - unsigned short *iptr = NULL, *icptr = NULL; struct map_session_data *sd = NULL; + unsigned short *icptr = NULL; struct party_data *p = NULL; struct guild *g = NULL; + short *iptr = NULL; int i, j; switch ( type ) { @@ -91,7 +92,7 @@ int instance_create(int owner_id, const char *name, enum instance_owner_type typ } ARR_FIND(0, instance->instances, i, instances[i].state == INSTANCE_FREE); - + if( i == instance->instances ) RECREATE(instances, struct instance_data, ++instance->instances); @@ -109,10 +110,9 @@ int instance_create(int owner_id, const char *name, enum instance_owner_type typ instances[i].vars = idb_alloc(DB_OPT_RELEASE_DATA); safestrncpy( instances[i].name, name, sizeof(instances[i].name) ); - instances[i].map = NULL; if( type != IOT_NONE ) { - ARR_FIND(0, *icptr, j, iptr[j] == 0); + ARR_FIND(0, *icptr, j, iptr[j] == -1); if( j == *icptr ) { switch( type ) { case IOT_CHAR: @@ -162,8 +162,8 @@ int instance_add_map(const char *name, int instance_id, bool usebasename, const return -4; } - ARR_FIND( instance->start_id, iMap->map_num, i, !map[i].name[0] ); // Searching for a Free Map - + ARR_FIND( instance->start_id, iMap->map_num, i, map[i].name[0] == 0 ); // Searching for a Free Map + if( i < iMap->map_num ) im = i; // Unused map found (old instance) else { @@ -370,6 +370,7 @@ void instance_del_map(int16 m) { iMap->removemapdb(&map[m]); memset(&map[m], 0x00, sizeof(map[0])); + map[m].name[0] = 0; map[m].instance_id = -1; map[m].mob_delete_timer = INVALID_TIMER; } @@ -386,13 +387,14 @@ int instance_destroy_timer(int tid, unsigned int tick, int id, intptr_t data) { * Removes a instance, all its maps and npcs. *--------------------------------------*/ void instance_destroy(int instance_id) { - unsigned short *iptr = NULL, *icptr = NULL; struct map_session_data *sd = NULL; + unsigned short *icptr = NULL; struct party_data *p = NULL; struct guild *g = NULL; - int last = 0, type, j; + short *iptr = NULL; + int type, j, last = 0; unsigned int now = (unsigned int)time(NULL); - + if( !instance->valid(instance_id) ) return; // nothing to do @@ -402,7 +404,7 @@ void instance_destroy(int instance_id) { type = 2; else type = 3; - + clif->instance(instance_id, 5, type); // Report users this instance has been destroyed switch ( instances[instance_id].owner_type ) { @@ -430,21 +432,21 @@ void instance_destroy(int instance_id) { icptr = &g->instances; break; default: - ShowError("instance_destroy: unknown type %d for owner_id %d and name %s.\n", instances[instance_id].owner_type,instances[instance_id].owner_id,instances[instance_id].name); + ShowError("instance_destroy: unknown type %d for owner_id %d and name '%s'.\n", instances[instance_id].owner_type,instances[instance_id].owner_id,instances[instance_id].name); break; } if( iptr != NULL ) { ARR_FIND(0, *icptr, j, iptr[j] == instance_id); if( j != *icptr ) - iptr[j] = 0; + iptr[j] = -1; } while( instances[instance_id].num_map && last != instances[instance_id].map[0] ) { // Remove all maps from instance last = instances[instance_id].map[0]; instance->del_map( instances[instance_id].map[0] ); } - + if( instances[instance_id].vars ) db_destroy(instances[instance_id].vars); @@ -455,10 +457,12 @@ void instance_destroy(int instance_id) { instances[instance_id].vars = NULL; - aFree(instances[instance_id].map); + if( instances[instance_id].map ) + aFree(instances[instance_id].map); - memset( &instances[instance_id], 0x00, sizeof(struct instance_data) ); - + instances[instance_id].map = NULL; + instances[instance_id].state = INSTANCE_FREE; + instances[instance_id].num_map = 0; } /*-------------------------------------- @@ -540,12 +544,15 @@ void instance_check_kick(struct map_session_data *sd) { void do_final_instance(void) { int i; - + for(i = 0; i < instance->instances; i++) { - instance_destroy(i); + instance->destroy(i); } - aFree(instances); + if( instances ) + aFree(instances); + + instance->instances = 0; } void do_init_instance(void) { diff --git a/src/map/map.c b/src/map/map.c index 956ae5969..74e2c74e0 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -5006,8 +5006,6 @@ void do_final(void) iMap->quit(sd); mapit->free(iter); - instance->final(); - /* prepares npcs for a faster shutdown process */ do_clear_npc(); @@ -5031,6 +5029,7 @@ void do_final(void) do_final_npc(); script->final(); itemdb->final(); + instance->final(); storage->final(); guild->final(); party->do_final_party(); diff --git a/src/map/npc.c b/src/map/npc.c index d90f87f5d..8381ac409 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -3838,8 +3838,10 @@ int npc_reload(void) { "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n" "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n", npc_id - npc_new_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob); - - instance->final(); + + for(i = 0; i < instance->instances; i++) { + instance->destroy(i); + } iMap->zone_init(); diff --git a/src/map/party.c b/src/map/party.c index adcb35c5a..306c68e3e 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -319,10 +319,12 @@ int party_recv_info(struct party* sp, int char_id) clif->party_option(p,sd,0x100); clif->party_info(p,NULL); for( j = 0; j < p->instances; j++ ) { - if( instances[p->instance[j]].idle_timer == INVALID_TIMER && instances[p->instance[j]].progress_timer == INVALID_TIMER ) - continue; - clif->instance_join(sd->fd, p->instance[j]); - break; + if( p->instance[j] >= 0 ) { + if( instances[p->instance[j]].idle_timer == INVALID_TIMER && instances[p->instance[j]].progress_timer == INVALID_TIMER ) + continue; + clif->instance_join(sd->fd, p->instance[j]); + break; + } } } if( char_id != 0 )// requester @@ -441,10 +443,12 @@ void party_member_joined(struct map_session_data *sd) int j; p->data[i].sd = sd; for( j = 0; j < p->instances; j++ ) { - if( instances[p->instance[j]].idle_timer == INVALID_TIMER && instances[p->instance[j]].progress_timer == INVALID_TIMER ) - continue; - clif->instance_join(sd->fd, p->instance[j]); - break; + if( p->instance[j] >= 0 ) { + if( instances[p->instance[j]].idle_timer == INVALID_TIMER && instances[p->instance[j]].progress_timer == INVALID_TIMER ) + continue; + clif->instance_join(sd->fd, p->instance[j]); + break; + } } } else sd->status.party_id = 0; //He does not belongs to the party really? @@ -502,10 +506,12 @@ int party_member_added(int party_id,int account_id,int char_id, int flag) clif->charnameupdate(sd); //Update char name's display [Skotlex] for( j = 0; j < p->instances; j++ ) { - if( instances[p->instance[j]].idle_timer == INVALID_TIMER && instances[p->instance[j]].progress_timer == INVALID_TIMER ) - continue; - clif->instance_join(sd->fd, p->instance[j]); - break; + if( p->instance[j] >= 0 ) { + if( instances[p->instance[j]].idle_timer == INVALID_TIMER && instances[p->instance[j]].progress_timer == INVALID_TIMER ) + continue; + clif->instance_join(sd->fd, p->instance[j]); + break; + } } return 0; @@ -594,8 +600,10 @@ int party_broken(int party_id) return 0; for( j = 0; j < p->instances; j++ ) { - instance->destroy( p->instance[j] ); - instances[p->instance[j]].owner_id = 0; + if( p->instance[j] >= 0 ) { + instance->destroy( p->instance[j] ); + instances[p->instance[j]].owner_id = 0; + } } for( i = 0; i < MAX_PARTY; i++ ) { diff --git a/src/map/party.h b/src/map/party.h index e1f2d3a3b..f215baa56 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -24,7 +24,7 @@ struct party_data { struct party party; struct party_member_data data[MAX_PARTY]; uint8 itemc; //For item distribution, position of last picker in party - unsigned short *instance; + short *instance; unsigned short instances; struct { unsigned monk : 1; //There's at least one monk in party? diff --git a/src/map/pc.c b/src/map/pc.c index 61655afc3..1a5822f81 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -4722,9 +4722,11 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y if( sd->instances ) { for( i = 0; i < sd->instances; i++ ) { - ARR_FIND(0, instances[sd->instance[i]].num_map, j, map[instances[sd->instance[i]].map[j]].instance_src_map == m && !map[instances[sd->instance[i]].map[j]].cName); - if( j != instances[sd->instance[i]].num_map ) - break; + if( sd->instance[i] >= 0 ) { + ARR_FIND(0, instances[sd->instance[i]].num_map, j, map[instances[sd->instance[i]].map[j]].instance_src_map == m && !map[instances[sd->instance[i]].map[j]].cName); + if( j != instances[sd->instance[i]].num_map ) + break; + } } if( i != sd->instances ) { m = instances[sd->instance[i]].map[j]; @@ -4734,9 +4736,11 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y } if ( !stop && sd->status.party_id && (p = party->search(sd->status.party_id)) && p->instances ) { for( i = 0; i < p->instances; i++ ) { - ARR_FIND(0, instances[p->instance[i]].num_map, j, map[instances[p->instance[i]].map[j]].instance_src_map == m && !map[instances[p->instance[i]].map[j]].cName); - if( j != instances[p->instance[i]].num_map ) - break; + if( p->instance[i] >= 0 ) { + ARR_FIND(0, instances[p->instance[i]].num_map, j, map[instances[p->instance[i]].map[j]].instance_src_map == m && !map[instances[p->instance[i]].map[j]].cName); + if( j != instances[p->instance[i]].num_map ) + break; + } } if( i != p->instances ) { m = instances[p->instance[i]].map[j]; @@ -4746,9 +4750,11 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y } if ( !stop && sd->status.guild_id && sd->guild && sd->guild->instances ) { for( i = 0; i < sd->guild->instances; i++ ) { - ARR_FIND(0, instances[sd->guild->instance[i]].num_map, j, map[instances[sd->guild->instance[i]].map[j]].instance_src_map == m && !map[instances[sd->guild->instance[i]].map[j]].cName); - if( j != instances[sd->guild->instance[i]].num_map ) - break; + if( sd->guild->instance[i] >= 0 ) { + ARR_FIND(0, instances[sd->guild->instance[i]].num_map, j, map[instances[sd->guild->instance[i]].map[j]].instance_src_map == m && !map[instances[sd->guild->instance[i]].map[j]].cName); + if( j != instances[sd->guild->instance[i]].num_map ) + break; + } } if( i != sd->guild->instances ) { m = instances[sd->guild->instance[i]].map[j]; diff --git a/src/map/pc.h b/src/map/pc.h index 298808d0d..442b55965 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -482,7 +482,7 @@ struct map_session_data { struct sc_display_entry **sc_display; unsigned char sc_display_count; - unsigned short *instance; + short *instance; unsigned short instances; /* Possible Thanks to Yommy~! */ diff --git a/src/map/script.c b/src/map/script.c index a61487332..bbae42c6f 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -16105,27 +16105,33 @@ BUILDIN(has_instance) { int i = 0, j = 0; if( sd->instances ) { for( i = 0; i < sd->instances; i++ ) { - ARR_FIND(0, instances[sd->instance[i]].num_map, j, map[instances[sd->instance[i]].map[j]].instance_src_map == m); - if( j != instances[sd->instance[i]].num_map ) - break; + if( sd->instance[i] >= 0 ) { + ARR_FIND(0, instances[sd->instance[i]].num_map, j, map[instances[sd->instance[i]].map[j]].instance_src_map == m); + if( j != instances[sd->instance[i]].num_map ) + break; + } } if( i != sd->instances ) instance_id = sd->instance[i]; } if( instance_id == -1 && sd->status.party_id && (p = party->search(sd->status.party_id)) && p->instances ) { for( i = 0; i < p->instances; i++ ) { - ARR_FIND(0, instances[p->instance[i]].num_map, j, map[instances[p->instance[i]].map[j]].instance_src_map == m); - if( j != instances[p->instance[i]].num_map ) - break; + if( p->instance[i] >= 0 ) { + ARR_FIND(0, instances[p->instance[i]].num_map, j, map[instances[p->instance[i]].map[j]].instance_src_map == m); + if( j != instances[p->instance[i]].num_map ) + break; + } } if( i != p->instances ) instance_id = p->instance[i]; } if( instance_id == -1 && sd->guild && sd->guild->instances ) { for( i = 0; i < sd->guild->instances; i++ ) { - ARR_FIND(0, instances[sd->guild->instance[i]].num_map, j, map[instances[sd->guild->instance[i]].map[j]].instance_src_map == m); - if( j != instances[sd->guild->instance[i]].num_map ) - break; + if( sd->guild->instance[i] >= 0 ) { + ARR_FIND(0, instances[sd->guild->instance[i]].num_map, j, map[instances[sd->guild->instance[i]].map[j]].instance_src_map == m); + if( j != instances[sd->guild->instance[i]].num_map ) + break; + } } if( i != sd->guild->instances ) instance_id = sd->guild->instance[i]; -- cgit v1.2.3-60-g2f50