From b8f6e16f9d1b7b20f1acb6b868c5fdbc07075f23 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Tue, 25 Aug 2015 13:23:23 -0400 Subject: [PATCH] Follow up to 9738c82 * Fixed some more memory leaks. * Added a few checks that were left out/removed by mistake. --- src/map/npc.c | 12 ++++++++--- src/map/script.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++- src/map/script.h | 4 +++- 3 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/map/npc.c b/src/map/npc.c index 9fe667f59b..292d78c865 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -1278,11 +1278,14 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd) *------------------------------------------*/ int npc_scriptcont(struct map_session_data* sd, int id, bool closing) { + struct block_list *target = map_id2bl(id); + nullpo_retr(1, sd); if( id != sd->npc_id ){ - TBL_NPC* nd_sd=(TBL_NPC*)map_id2bl(sd->npc_id); - TBL_NPC* nd=(TBL_NPC*)map_id2bl(id); + TBL_NPC* nd_sd = (TBL_NPC*)map_id2bl(sd->npc_id); + TBL_NPC* nd = BL_CAST(BL_NPC, target); + ShowDebug("npc_scriptcont: %s (sd->npc_id=%d) is not %s (id=%d).\n", nd_sd?(char*)nd_sd->name:"'Unknown NPC'", (int)sd->npc_id, nd?(char*)nd->name:"'Unknown NPC'", (int)id); @@ -1290,7 +1293,7 @@ int npc_scriptcont(struct map_session_data* sd, int id, bool closing) } if(id != fake_nd->bl.id) { // Not item script - if ((npc_checknear(sd,map_id2bl(id))) == NULL){ + if ((npc_checknear(sd, target)) == NULL) { ShowWarning("npc_scriptcont: failed npc_checknear test.\n"); return 1; } @@ -1305,6 +1308,9 @@ int npc_scriptcont(struct map_session_data* sd, int id, bool closing) if( sd->progressbar.npc_id && DIFF_TICK(sd->progressbar.timeout,gettick()) > 0 ) return 1; + if (!sd->st) + return 1; + if( closing && sd->st && sd->st->state == CLOSE ) sd->st->state = END; diff --git a/src/map/script.c b/src/map/script.c index 754905e393..15097f854c 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -3391,6 +3391,8 @@ void script_free_code(struct script_code* code) { nullpo_retv(code); + if (code->instances) + script_stop_instances(code); script_free_vars(code->local.vars); if (code->local.arrays) code->local.arrays->destroy(code->local.arrays, script_free_array_db); @@ -3424,6 +3426,14 @@ struct script_state* script_alloc_state(struct script_code* rootscript, int pos, st->oid = oid; st->sleep.timer = INVALID_TIMER; st->npc_item_flag = battle_config.item_enabled_npc; + + if( st->script->instances != USHRT_MAX ) + st->script->instances++; + else { + struct npc_data *nd = map_id2nd(oid); + + ShowError("Over 65k instances of '%s' script are being run!\n",nd ? nd->name : "unknown"); + } if (!st->script->local.vars) st->script->local.vars = i64db_alloc(DB_OPT_RELEASE_DATA); @@ -3442,9 +3452,20 @@ struct script_state* script_alloc_state(struct script_code* rootscript, int pos, void script_free_state(struct script_state* st) { if (idb_exists(st_db, st->id)) { + struct map_session_data *sd = st->rid ? map_id2sd(st->rid) : NULL; + if (st->bk_st) // backup was not restored ShowDebug("script_free_state: Previous script state lost (rid=%d, oid=%d, state=%d, bk_npcid=%d).\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid); + if (sd && sd->st == st) { // Current script is aborted. + if(sd->state.using_fake_npc) { + clif_clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd); + sd->state.using_fake_npc = 0; + } + sd->st = NULL; + sd->npc_id = 0; + } + if (st->sleep.timer != INVALID_TIMER) delete_timer(st->sleep.timer, run_script_timer); if (st->stack) { @@ -3456,7 +3477,7 @@ void script_free_state(struct script_state* st) ers_free(stack_ers, st->stack); st->stack = NULL; } - if (st->script) { + if (st->script && st->script->instances != USHRT_MAX && --st->script->instances == 0) { if (st->script->local.vars && !db_size(st->script->local.vars)) { script_free_vars(st->script->local.vars); st->script->local.vars = NULL; @@ -3942,6 +3963,23 @@ void run_script(struct script_code *rootscript, int pos, int rid, int oid) run_script_main(st); } +void script_stop_instances(struct script_code *code) { + DBIterator *iter; + struct script_state* st; + + if( !active_scripts ) + return; // Don't even bother. + + iter = db_iterator(st_db); + + for( st = dbi_first(iter); dbi_exists(iter); st = dbi_next(iter) ) { + if( st->script == code ) + script_free_state(st); + } + + dbi_destroy(iter); +} + /*========================================== * Timer function for sleep *------------------------------------------*/ @@ -9054,6 +9092,18 @@ BUILDIN_FUNC(end) st->state = END; + if (st->stack->defsp >= 1 && st->stack->stack_data[st->stack->defsp-1].type == C_RETINFO) { + int i; + + for(i = 0; i < st->stack->sp; i++) { + if (st->stack->stack_data[i].type == C_RETINFO) { // Grab the first, aka the original + struct script_retinfo *ri = st->stack->stack_data[i].u.ri; + st->script = ri->script; + break; + } + } + } + if( st->mes_active ) st->mes_active = 0; diff --git a/src/map/script.h b/src/map/script.h index 8c50dda935..742ff6de4b 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -234,6 +234,7 @@ struct script_code { int script_size; unsigned char* script_buf; struct reg_db local; + unsigned short instances; }; struct script_stack { @@ -256,7 +257,7 @@ struct script_state { int pos; enum e_script_state state; int rid,oid; - struct script_code *script, *scriptroot; + struct script_code *script; struct sleep_data { int tick,timer,charid; } sleep; @@ -319,6 +320,7 @@ void pop_stack(struct script_state* st, int start, int end); int run_script_timer(int tid, unsigned int tick, int id, intptr_t data); void run_script_main(struct script_state *st); +void script_stop_instances(struct script_code *code); struct linkdb_node* script_erase_sleepdb(struct linkdb_node *n); void script_free_code(struct script_code* code); void script_free_vars(struct DBMap *storage);