summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshennetsind <ind@henn.et>2013-06-24 13:13:27 -0300
committershennetsind <ind@henn.et>2013-06-24 13:13:27 -0300
commit4ff67a9c9977e216c5b63bf5c80480dba1e2fcab (patch)
tree8e59ec1c7f180bce2f1ec32be0c5de55a77f5e8f
parent15cf156a3229532ffb2db0f78b29da228e0b2cc7 (diff)
downloadhercules-4ff67a9c9977e216c5b63bf5c80480dba1e2fcab.tar.gz
hercules-4ff67a9c9977e216c5b63bf5c80480dba1e2fcab.tar.bz2
hercules-4ff67a9c9977e216c5b63bf5c80480dba1e2fcab.tar.xz
hercules-4ff67a9c9977e216c5b63bf5c80480dba1e2fcab.zip
Fixed Bug #7412
Special Thanks to shenhuyong http://hercules.ws/board/tracker/issue-7412-create-instancereloadscript-causes-map-server-crash/ Signed-off-by: shennetsind <ind@henn.et>
-rw-r--r--src/common/mmo.h2
-rw-r--r--src/map/instance.c45
-rw-r--r--src/map/map.c3
-rw-r--r--src/map/npc.c6
-rw-r--r--src/map/party.c36
-rw-r--r--src/map/party.h2
-rw-r--r--src/map/pc.c24
-rw-r--r--src/map/pc.h2
-rw-r--r--src/map/script.c24
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];