From b0bf26b076dcc5a6f1d6ecddde89948366e96a1a Mon Sep 17 00:00:00 2001 From: FlavioJS Date: Tue, 30 Dec 2008 03:27:46 +0000 Subject: * Changes to the script engine: - script ends when run_func can't find the buildin command. (script engine error) - run_script_main doesn't change RERUNLINE to RUN automatically, the buildin command that set it is responsible for that now. The buildin command can use this to detect a rerun. - created functions to alloc/free a script_state. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@13426 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/npc.c | 4 +-- src/map/script.c | 107 ++++++++++++++++++++++++++++++++----------------------- src/map/script.h | 5 +-- src/map/unit.c | 1 + 4 files changed, 68 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/map/npc.c b/src/map/npc.c index 17ba64984..fd44ded3a 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -163,9 +163,7 @@ int npc_event_dequeue(struct map_session_data* sd) sd->state.using_fake_npc = 0; } if (sd->st) { - sd->st->pos = -1; - script_free_stack(sd->st->stack); - aFree(sd->st); + script_free_state(sd->st); sd->st = NULL; } sd->npc_id = 0; diff --git a/src/map/script.c b/src/map/script.c index 8bd8c9ef1..180349c17 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -273,7 +273,7 @@ typedef struct script_function { extern script_function buildin_func[]; -static struct linkdb_node *sleep_db; +static struct linkdb_node* sleep_db;// int oid -> struct script_state* /*========================================== * ローカルプロトタイプ宣言 (必要な物のみ) @@ -2520,7 +2520,8 @@ void script_free_vars(struct linkdb_node **node) /*========================================== * Free's the whole stack. Invoked when clearing a character. [Skotlex] *------------------------------------------*/ -void script_free_stack(struct script_stack *stack) +/// @deprecated will be removed later [FlavioJS] +static void script_free_stack(struct script_stack *stack) { int i; for(i = 0; i < stack->sp; i++) { @@ -2546,6 +2547,45 @@ void script_free_code(struct script_code* code) aFree( code ); } +/// Creates a new script state. +/// +/// @param script Script code +/// @param pos Position in the code +/// @param rid Who is running the script (attached player) +/// @param oid Where the code is being run (npc 'object') +/// @return Script state +struct script_state* script_alloc_state(struct script_code* script, int pos, int rid, int oid) +{ + struct script_state* st; + CREATE(st, struct script_state, 1); + st->stack = (struct script_stack*)aMalloc(sizeof(struct script_stack)); + st->stack->sp = 0; + st->stack->sp_max = 64; + CREATE(st->stack->stack_data, struct script_data, st->stack->sp_max); + st->stack->defsp = st->stack->sp; + CREATE(st->stack->var_function, struct linkdb_node*, 1); + st->state = RUN; + st->script = script; + //st->scriptroot = script; + st->pos = pos; + st->rid = rid; + st->oid = oid; + st->sleep.timer = INVALID_TIMER; + return st; +} + +/// Frees a script state. +/// +/// @param st Script state +void script_free_state(struct script_state* st) +{ + if( st->sleep.timer != INVALID_TIMER ) + delete_timer(st->sleep.timer, run_script_timer); + script_free_stack(st->stack); + st->pos = -1; + aFree(st); +} + // // 実行部main // @@ -2885,9 +2925,10 @@ int run_func(struct script_state *st) if (str_data[func].func(st)) //Report error script_reportsrc(st); } else { - ShowError("run_func : %s? (%d(%d))\n", get_str(func),func,str_data[func].type); - script_pushint(st,0); + ShowError("script:run_func: missing buildin command '%s' (id=%d type=%s)\n", get_str(func), func, script_op2name(str_data[func].type)); + script_pushnil(st); script_reportsrc(st); + st->state = END; } // Stack's datum are used when re-run functions [Eoe] @@ -2932,31 +2973,14 @@ void run_script_main(struct script_state *st); void run_script(struct script_code *rootscript,int pos,int rid,int oid) { struct script_state *st; - TBL_PC *sd=NULL; - if(rootscript==NULL || pos<0) + if( rootscript == NULL || pos < 0 ) return; - if (rid) sd = map_id2sd(rid); - if (sd && sd->st && sd->st->scriptroot == rootscript && sd->st->pos == pos){ - //Resume script. - st = sd->st; - } else { - st = (struct script_state*)aCalloc(sizeof(struct script_state), 1); - // the script is different, make new script_state and stack - st->stack = (struct script_stack*)aMalloc (sizeof(struct script_stack)); - st->stack->sp=0; - st->stack->sp_max=64; - st->stack->stack_data = (struct script_data *)aCalloc(st->stack->sp_max,sizeof(st->stack->stack_data[0])); - st->stack->defsp = st->stack->sp; - st->stack->var_function = (struct linkdb_node**)aCalloc(1, sizeof(struct linkdb_node*)); - st->state = RUN; - st->script = rootscript; - } - st->pos = pos; - st->rid = rid; - st->oid = oid; - st->sleep.timer = INVALID_TIMER; + // TODO In jAthena, this function can take over the pending script in the player. [FlavioJS] + // It is unclear how that can be triggered, so it needs the be traced/checked in more detail. + // NOTE At the time of this change, this function wasn't capable of taking over the script state because st->scriptroot was never set. + st = script_alloc_state(rootscript, pos, rid, oid); run_script_main(st); } @@ -2968,10 +2992,7 @@ void script_stop_sleeptimers(int id) st = (struct script_state*)linkdb_erase(&sleep_db,(void*)id); if( st == NULL ) break; // no more sleep timers - if( st->sleep.timer != INVALID_TIMER ) - delete_timer(st->sleep.timer, run_script_timer); - script_free_stack(st->stack); - aFree(st); + script_free_state(st); } } @@ -3036,7 +3057,7 @@ void run_script_main(struct script_state *st) int bk_npcid = 0; struct script_stack *stack=st->stack; - sd = st->rid?map_id2sd(st->rid):NULL; + sd = map_id2sd(st->rid); if(sd){ if(sd->st != st){ @@ -3048,7 +3069,6 @@ void run_script_main(struct script_state *st) } if(st->state == RERUNLINE) { - st->state = RUN; run_func(st); if(st->state == GOTO) st->state = RUN; @@ -3188,16 +3208,13 @@ void run_script_main(struct script_state *st) if (sd->state.reg_dirty&1) intif_saveregistry(sd,1); } - st->pos = -1; - script_free_stack (st->stack); - aFree(st); + script_free_state(st); + st = NULL; } if (bk_st) { //Remove previous script - bk_st->pos = -1; - script_free_stack(bk_st->stack); - aFree(bk_st); + script_free_state(bk_st); bk_st = NULL; } @@ -3326,8 +3343,7 @@ int do_final_script() struct linkdb_node *n = (struct linkdb_node *)sleep_db; while(n) { struct script_state *st = (struct script_state *)n->data; - script_free_stack(st->stack); - aFree(st); + script_free_state(st); n = n->next; } linkdb_final(&sleep_db); @@ -3362,10 +3378,7 @@ int script_reload() struct linkdb_node *n = (struct linkdb_node *)sleep_db; while(n) { struct script_state *st = (struct script_state *)n->data; - if( st->sleep.timer != INVALID_TIMER ) - delete_timer(st->sleep.timer, run_script_timer); - script_free_stack(st->stack); - aFree(st); + script_free_state(st); n = n->next; } linkdb_final(&sleep_db); @@ -3660,6 +3673,7 @@ BUILDIN_FUNC(select) } pc_setreg(sd, add_str("@menu"), menu); script_pushint(st, menu); + st->state = RUN; } return 0; } @@ -3707,6 +3721,7 @@ BUILDIN_FUNC(prompt) sd->state.menu_or_input = 0; pc_setreg(sd, add_str("@menu"), 0xff); script_pushint(st, 0xff); + st->state = RUN; } else {// return selected option @@ -3722,6 +3737,7 @@ BUILDIN_FUNC(prompt) } pc_setreg(sd, add_str("@menu"), menu); script_pushint(st, menu); + st->state = RUN; } return 0; } @@ -4373,6 +4389,7 @@ BUILDIN_FUNC(input) set_reg(st, sd, uid, name, (void*)cap_value(amount,min,max), script_getref(st,2)); script_pushint(st, (amount > max ? 1 : amount < min ? -1 : 0)); } + st->state = RUN; } return 0; } @@ -12733,6 +12750,7 @@ BUILDIN_FUNC(sleep) } else {// sleep time is over + st->state = RUN; st->sleep.tick = 0; } return 0; @@ -12759,6 +12777,7 @@ BUILDIN_FUNC(sleep2) } else {// sleep time is over + st->state = RUN; st->sleep.tick = 0; script_pushint(st, (map_id2sd(st->rid)!=NULL)); } diff --git a/src/map/script.h b/src/map/script.h index 2e10b3303..fc6422bc5 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -89,7 +89,7 @@ struct script_stack { int sp_max;// capacity of the stack int defsp; struct script_data *stack_data;// stack - struct linkdb_node **var_function; // 関数依存変数 + struct linkdb_node **var_function; // ヨ斥耐 }; @@ -141,9 +141,10 @@ void run_script_main(struct script_state *st); void script_stop_sleeptimers(int id); struct linkdb_node* script_erase_sleepdb(struct linkdb_node *n); -void script_free_stack(struct script_stack*); void script_free_code(struct script_code* code); void script_free_vars(struct linkdb_node **node); +struct script_state* script_alloc_state(struct script_code* script, int pos, int rid, int oid); +void script_free_state(struct script_state* st); struct DBMap* script_get_label_db(void); struct DBMap* script_get_userfunc_db(void); diff --git a/src/map/unit.c b/src/map/unit.c index 812c70b47..6695abf6b 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1961,6 +1961,7 @@ int unit_free(struct block_list *bl, int clrtype) sd->regstr_num = 0; } //Tell the script to end, not delete it, it will free itself when necessary [Kevin] + // TODO review this assumption, possible source of memory leaks [FlavioJS] if( sd->st ) { sd->st->rid = 0; -- cgit v1.2.3-60-g2f50