summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorshennetsind <ind@henn.et>2013-06-30 12:29:54 -0300
committershennetsind <ind@henn.et>2013-06-30 12:29:54 -0300
commit3e54d00ad3e1f6fd56aace6f227c66a5b67eb3ea (patch)
tree19af3dd738e37b5236552e6f97c4a83d5305e2c8 /src
parent7c479ad6027ccbce605ebb49c5e8900037772dd5 (diff)
downloadhercules-3e54d00ad3e1f6fd56aace6f227c66a5b67eb3ea.tar.gz
hercules-3e54d00ad3e1f6fd56aace6f227c66a5b67eb3ea.tar.bz2
hercules-3e54d00ad3e1f6fd56aace6f227c66a5b67eb3ea.tar.xz
hercules-3e54d00ad3e1f6fd56aace6f227c66a5b67eb3ea.zip
Fixed script timer problem
Special Thanks to Igniz for bringing it to my attention, ALSO: over 10% script parsing speed boost!<3. Signed-off-by: shennetsind <ind@henn.et>
Diffstat (limited to 'src')
-rw-r--r--src/map/npc.c113
-rw-r--r--src/map/script.c60
-rw-r--r--src/map/script.h12
3 files changed, 101 insertions, 84 deletions
diff --git a/src/map/npc.c b/src/map/npc.c
index 77758bc00..a71bc36ca 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -1862,7 +1862,7 @@ int npc_unload(struct npc_data* nd, bool single) {
aFree(nd->u.scr.timer_event);
if (nd->src_id == 0) {
if(nd->u.scr.script) {
- script_stop_instances(nd->bl.id);
+ script_stop_instances(nd->u.scr.script);
script_free_code(nd->u.scr.script);
nd->u.scr.script = NULL;
}
@@ -2275,52 +2275,34 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
return strchr(start,'\n');// continue
}
-/**
- * NPC other label
- * Not sure, seem to add label in a chainlink
- * @see DBApply
- */
-int npc_convertlabel_db(DBKey key, DBData *data, va_list ap)
-{
- const char* lname = (const char*)key.str;
- int lpos = DB->data2i(data);
- struct npc_label_list** label_list;
- int* label_list_num;
- const char* filepath;
- struct npc_label_list* label;
- const char *p;
- int len;
-
- nullpo_ret(label_list = va_arg(ap,struct npc_label_list**));
- nullpo_ret(label_list_num = va_arg(ap,int*));
- nullpo_ret(filepath = va_arg(ap,const char*));
-
- // In case of labels not terminated with ':', for user defined function support
- p = lname;
- while( ISALNUM(*p) || *p == '_' )
- ++p;
- len = p-lname;
-
- // here we check if the label fit into the buffer
- if( len > 23 )
- {
- ShowError("npc_parse_script: label name longer than 23 chars! '%s'\n (%s)", lname, filepath);
- return 0;
- }
-
- if( *label_list == NULL )
- {
- *label_list = (struct npc_label_list *) aCalloc (1, sizeof(struct npc_label_list));
- *label_list_num = 0;
- } else
- *label_list = (struct npc_label_list *) aRealloc (*label_list, sizeof(struct npc_label_list)*(*label_list_num+1));
- label = *label_list+*label_list_num;
+void npc_convertlabel_db(struct npc_label_list* label_list, const char *filepath) {
+ int i;
+
+ for( i = 0; i < script->label_count; i++ ) {
+ const char* lname = get_str(script->labels[i].key);
+ int lpos = script->labels[i].pos;
+ struct npc_label_list* label;
+ const char *p;
+ int len;
+
+ // In case of labels not terminated with ':', for user defined function support
+ p = lname;
- safestrncpy(label->name, lname, sizeof(label->name));
- label->pos = lpos;
- ++(*label_list_num);
+ while( ISALNUM(*p) || *p == '_' )
+ ++p;
+ len = p-lname;
- return 0;
+ // here we check if the label fit into the buffer
+ if( len > 23 ) {
+ ShowError("npc_parse_script: label name longer than 23 chars! '%s'\n (%s)", lname, filepath);
+ return;
+ }
+
+ label = &label_list[i];
+
+ safestrncpy(label->name, lname, sizeof(label->name));
+ label->pos = lpos;
+ }
}
// Skip the contents of a script.
@@ -2388,7 +2370,7 @@ static const char* npc_skip_script(const char* start, const char* buffer, const
static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, bool runOnInit) {
int x, y, dir = 0, m, xs = 0, ys = 0, class_ = 0; // [Valaris] thanks to fov
char mapname[32];
- struct script_code *script;
+ struct script_code *scriptroot;
int i;
const char* end;
const char* script_start;
@@ -2426,14 +2408,13 @@ static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, cons
if( end == NULL )
return NULL;// (simple) parse error, don't continue
- script = parse_script(script_start, filepath, strline(buffer,script_start-buffer), SCRIPT_USE_LABEL_DB);
+ scriptroot = parse_script(script_start, filepath, strline(buffer,script_start-buffer), SCRIPT_USE_LABEL_DB);
label_list = NULL;
label_list_num = 0;
- if( script )
- {
- DBMap* label_db = script_get_label_db();
- label_db->foreach(label_db, npc_convertlabel_db, &label_list, &label_list_num, filepath);
- db_clear(label_db); // not needed anymore, so clear the db
+ if( script->label_count ) {
+ CREATE(label_list,struct npc_label_list,script->label_count);
+ label_list_num = script->label_count;
+ npc_convertlabel_db(label_list,filepath);
}
CREATE(nd, struct npc_data, 1);
@@ -2458,7 +2439,7 @@ static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, cons
nd->bl.id = npc_get_new_npc_id();
nd->class_ = class_;
nd->speed = 200;
- nd->u.scr.script = script;
+ nd->u.scr.script = scriptroot;
nd->u.scr.label_list = label_list;
nd->u.scr.label_list_num = label_list_num;
@@ -3782,18 +3763,22 @@ int npc_reload(void) {
db_clear(npcname_db);
db_clear(ev_db);
+ npc_last_npd = NULL;
+ npc_last_path = NULL;
+ npc_last_ref = NULL;
+
//Remove all npcs/mobs. [Skotlex]
iter = mapit_geteachiddb();
for( bl = (struct block_list*)mapit->first(iter); mapit->exists(iter); bl = (struct block_list*)mapit->next(iter) ) {
switch(bl->type) {
- case BL_NPC:
- if( bl->id != fake_nd->bl.id )// don't remove fake_nd
- npc_unload((struct npc_data *)bl, false);
- break;
- case BL_MOB:
- unit_free(bl,CLR_OUTSIGHT);
- break;
+ case BL_NPC:
+ if( bl->id != fake_nd->bl.id )// don't remove fake_nd
+ npc_unload((struct npc_data *)bl, false);
+ break;
+ case BL_MOB:
+ unit_free(bl,CLR_OUTSIGHT);
+ break;
}
}
mapit->free(iter);
@@ -3970,10 +3955,14 @@ int do_init_npc(void)
ev_db = strdb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA),2*NAME_LENGTH+2+1);
npcname_db = strdb_alloc(DB_OPT_BASE,NAME_LENGTH);
- npc_path_db = strdb_alloc(DB_OPT_BASE|DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA,80);
+ npc_path_db = strdb_alloc(DB_OPT_BASE|DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA,0);
timer_event_ers = ers_new(sizeof(struct timer_event_data),"clif.c::timer_event_ers",ERS_OPT_NONE);
+ npc_last_npd = NULL;
+ npc_last_path = NULL;
+ npc_last_ref = NULL;
+
// process all npc files
ShowStatus("Loading NPCs...\r");
for( file = npc_src_files; file != NULL; file = file->next ) {
@@ -3988,7 +3977,7 @@ int do_init_npc(void)
"\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n"
"\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n",
npc_id - START_NPC_NUM, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
-
+
iMap->zone_init();
npc->motd = npc_name2id("HerculesMOTD"); /* [Ind/Hercules] */
diff --git a/src/map/script.c b/src/map/script.c
index 354ec0522..858c66874 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -97,10 +97,8 @@ int str_hash[SCRIPT_HASH_SIZE];
//#define SCRIPT_HASH_SDBM
#define SCRIPT_HASH_ELF
-static DBMap* scriptlabel_db=NULL; // const char* label_name -> int script_pos
static DBMap* userfunc_db=NULL; // const char* func_name -> struct script_code*
static int parse_options=0;
-DBMap* script_get_label_db(void){ return scriptlabel_db; }
DBMap* script_get_userfunc_db(void){ return userfunc_db; }
// important buildin function references for usage in scripts
@@ -1650,7 +1648,7 @@ const char* parse_syntax(const char* p)
script->str_data[l].type = C_USERFUNC;
set_label(l, script_pos, p);
if( parse_options&SCRIPT_USE_LABEL_DB )
- strdb_iput(scriptlabel_db, get_str(l), script_pos);
+ script->label_add(l,script_pos);
}
else
disp_error_message("parse_syntax:function: function name is invalid", func_name);
@@ -2090,7 +2088,7 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
// who called parse_script is responsible for clearing the database after using it, but just in case... lets clear it here
if( options&SCRIPT_USE_LABEL_DB )
- db_clear(scriptlabel_db);
+ script->label_count = 0;
parse_options = options;
if( setjmp( error_jump ) != 0 ) {
@@ -2164,7 +2162,7 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
i=add_word(p);
set_label(i,script_pos,p);
if( parse_options&SCRIPT_USE_LABEL_DB )
- strdb_iput(scriptlabel_db, get_str(i), script_pos);
+ script->label_add(i,script_pos);
p=tmpp+1;
p=skip_space(p);
continue;
@@ -3286,7 +3284,7 @@ void run_script(struct script_code *rootscript,int pos,int rid,int oid) {
run_script_main(st);
}
-void script_stop_instances(int id) {
+void script_stop_instances(struct script_code *code) {
DBIterator *iter;
struct script_state* st;
@@ -3296,7 +3294,7 @@ void script_stop_instances(int id) {
iter = db_iterator(script->st_db);
for( st = dbi_first(iter); dbi_exists(iter); st = dbi_next(iter) ) {
- if( st->oid == id ) {
+ if( st->script == code ) {
script_free_state(st);
}
}
@@ -3308,17 +3306,19 @@ void script_stop_instances(int id) {
* Timer function for sleep
*------------------------------------------*/
int run_script_timer(int tid, unsigned int tick, int id, intptr_t data) {
- struct script_state *st = (struct script_state *)data;
- TBL_PC *sd = iMap->id2sd(st->rid);
+ struct script_state *st = idb_get(script->st_db,(int)data);
+ if( st ) {
+ TBL_PC *sd = iMap->id2sd(st->rid);
- if((sd && sd->status.char_id != id) || (st->rid && !sd)) { //Character mismatch. Cancel execution.
- st->rid = 0;
- st->state = END;
+ if((sd && sd->status.char_id != id) || (st->rid && !sd)) { //Character mismatch. Cancel execution.
+ st->rid = 0;
+ st->state = END;
+ }
+ st->sleep.timer = INVALID_TIMER;
+ if(st->state != RERUNLINE)
+ st->sleep.tick = 0;
+ run_script_main(st);
}
- st->sleep.timer = INVALID_TIMER;
- if(st->state != RERUNLINE)
- st->sleep.tick = 0;
- run_script_main(st);
return 0;
}
@@ -3514,7 +3514,7 @@ void run_script_main(struct script_state *st)
sd = iMap->id2sd(st->rid); // Get sd since script might have attached someone while running. [Inkfish]
st->sleep.charid = sd?sd->status.char_id:0;
st->sleep.timer = iTimer->add_timer(iTimer->gettick()+st->sleep.tick,
- run_script_timer, st->sleep.charid, (intptr_t)st);
+ run_script_timer, st->sleep.charid, (intptr_t)st->id);
} else if(st->state != END && st->rid){
//Resume later (st is already attached to player).
if(st->bk_st) {
@@ -3761,7 +3761,6 @@ void do_final_script(void) {
mapreg_final();
- db_destroy(scriptlabel_db);
userfunc_db->destroy(userfunc_db, db_script_free_code_sub);
autobonus_db->destroy(autobonus_db, db_script_free_code_sub);
@@ -3817,6 +3816,9 @@ void do_final_script(void) {
ers_destroy(script->stack_ers);
db_destroy(script->st_db);
+
+ if( script->labels != NULL )
+ aFree(script->labels);
}
/*==========================================
* Initialization
@@ -3824,7 +3826,6 @@ void do_final_script(void) {
void do_init_script(void) {
script->st_db = idb_alloc(DB_OPT_BASE);
userfunc_db = strdb_alloc(DB_OPT_DUP_KEY,0);
- scriptlabel_db = strdb_alloc(DB_OPT_DUP_KEY,50);
autobonus_db = strdb_alloc(DB_OPT_DUP_KEY,0);
script->st_ers = ers_new(sizeof(struct script_state), "script.c::st_ers", ERS_OPT_NONE);
@@ -3844,7 +3845,7 @@ int script_reload() {
struct script_state *st;
userfunc_db->clear(userfunc_db, db_script_free_code_sub);
- db_clear(scriptlabel_db);
+ script->label_count = 0;
for( i = 0; i < atcommand->binding_count; i++ ) {
aFree(atcommand->binding[i]);
@@ -18013,6 +18014,19 @@ void script_parse_builtin(void) {
}
}
+void script_label_add(int key, int pos) {
+ int idx = script->label_count;
+
+ if( script->labels_size == script->label_count ) {
+ script->labels_size += 1024;
+ RECREATE(script->labels, struct script_label_entry, script->labels_size);
+ }
+
+ script->labels[idx].key = key;
+ script->labels[idx].pos = pos;
+ script->label_count++;
+}
+
void script_defaults(void) {
script = &script_s;
@@ -18042,6 +18056,10 @@ void script_defaults(void) {
script->current_item_id = 0;
+ script->labels = NULL;
+ script->label_count = 0;
+ script->labels_size = 0;
+
script->init = do_init_script;
script->final = do_final_script;
@@ -18067,4 +18085,6 @@ void script_defaults(void) {
script->queue_remove = script_hqueue_remove;
script->queue_create = script_hqueue_create;
script->queue_clear = script_hqueue_clear;
+
+ script->label_add = script_label_add;
}
diff --git a/src/map/script.h b/src/map/script.h
index a77e957c0..902125681 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -191,14 +191,13 @@ int set_var(struct map_session_data *sd, char *name, void *val);
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(int id);
+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);
struct script_state* script_alloc_state(struct script_code* rootscript, 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);
void script_run_autobonus(const char *autobonus,int id, int pos);
@@ -231,6 +230,10 @@ struct str_data_struct {
int next;
};
+struct script_label_entry {
+ int key,pos;
+};
+
///////////////////////////////////////////////////////////////////////////////
//## TODO possible enhancements: [FlavioJS]
// - 'callfunc' supporting labels in the current npc "::LabelName"
@@ -359,6 +362,10 @@ struct script_interface {
int word_size;
/* */
unsigned short current_item_id;
+ /* */
+ struct script_label_entry *labels;
+ int label_count;
+ int labels_size;
/* */
void (*init) (void);
void (*final) (void);
@@ -378,6 +385,7 @@ struct script_interface {
void (*set_constant) (const char* name, int value, bool isparameter);
void (*set_constant2) (const char *name, int value, bool isparameter);
bool (*get_constant) (const char* name, int* value);
+ void (*label_add)(int key, int pos);
/* */
struct hQueue *(*queue) (int idx);
bool (*queue_add) (int idx, int var);