summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshennetsind <shennetsind@54d463be-8e91-2dee-dedb-b68131a5f0ec>2012-07-23 19:26:50 +0000
committershennetsind <shennetsind@54d463be-8e91-2dee-dedb-b68131a5f0ec>2012-07-23 19:26:50 +0000
commit98e833dc83ad9f0642bdbf6b90b239704292f15f (patch)
tree73194653b1a88d67d8608d9caaac7f5119a56c6d
parent81bfbbfb9c0f5af32e55f66ccea2d444eb76cabc (diff)
downloadhercules-98e833dc83ad9f0642bdbf6b90b239704292f15f.tar.gz
hercules-98e833dc83ad9f0642bdbf6b90b239704292f15f.tar.bz2
hercules-98e833dc83ad9f0642bdbf6b90b239704292f15f.tar.xz
hercules-98e833dc83ad9f0642bdbf6b90b239704292f15f.zip
Follow up r16471 improved overall feature performance by making the bind list a pointer array, this also allows the system to have a unlimited amount of atcommand bind instances. also fixed a memory leak that'd be caused when npc_do_atcmd_event fails (e.g. when target npc is manually reloaded)
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@16485 54d463be-8e91-2dee-dedb-b68131a5f0ec
-rw-r--r--src/map/atcommand.c23
-rw-r--r--src/map/atcommand.h11
-rw-r--r--src/map/npc.c25
-rw-r--r--src/map/script.c115
4 files changed, 112 insertions, 62 deletions
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 15f75d55a..6eeb5ec9f 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -57,6 +57,8 @@
typedef struct AtCommandInfo AtCommandInfo;
typedef struct AliasInfo AliasInfo;
+int atcmd_binding_count = 0;
+
struct AtCommandInfo {
char command[ATCOMMAND_LENGTH];
AtCommandFunc func;
@@ -86,14 +88,15 @@ static const char* atcommand_checkalias(const char *aliasname); // @help
static void atcommand_get_suggestions(struct map_session_data* sd, const char *name, bool atcommand); // @help
// @commands (script-based)
-struct Atcmd_Binding* get_atcommandbind_byname(const char* name)
-{
+struct atcmd_binding_data* get_atcommandbind_byname(const char* name) {
int i = 0;
+
if( *name == atcommand_symbol || *name == charcommand_symbol )
name++; // for backwards compatibility
- ARR_FIND( 0, ARRAYLENGTH(atcmd_binding), i, strcmp(atcmd_binding[i].command, name) == 0 );
- return ( i < ARRAYLENGTH(atcmd_binding) ) ? &atcmd_binding[i] : NULL;
- return NULL;
+
+ ARR_FIND( 0, atcmd_binding_count, i, strcmp(atcmd_binding[i]->command, name) == 0 );
+
+ return ( i < atcmd_binding_count ) ? atcmd_binding[i] : NULL;
}
//-----------------------------------------------------------
@@ -8998,9 +9001,6 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
TBL_PC * ssd = NULL; //sd for target
AtCommandInfo * info;
- // @commands (script based)
- Atcmd_Binding * binding;
-
nullpo_retr(false, sd);
//Shouldn't happen
@@ -9079,11 +9079,12 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
params[0] = '\0';
// @commands (script based)
- if(type == 1) {
+ if(type == 1 && atcmd_binding_count > 0) {
+ struct atcmd_binding_data * binding;
+
// Check if the command initiated is a character command
if (*message == charcommand_symbol &&
- (ssd = map_nick2sd(charname)) == NULL && (ssd = map_nick2sd(charname2)) == NULL )
- {
+ (ssd = map_nick2sd(charname)) == NULL && (ssd = map_nick2sd(charname2)) == NULL ) {
sprintf(output, "%s failed. Player not found.", command);
clif_displaymessage(fd, output);
return true;
diff --git a/src/map/atcommand.h b/src/map/atcommand.h
index 9bc844664..8affa4c26 100644
--- a/src/map/atcommand.h
+++ b/src/map/atcommand.h
@@ -34,17 +34,18 @@ const char* msg_txt(int msg_number);
int msg_config_read(const char* cfgName);
void do_final_msg(void);
-#define MAX_ATCMD_BINDINGS 100
+extern int atcmd_binding_count;
// @commands (script based)
-typedef struct Atcmd_Binding {
+struct atcmd_binding_data {
char command[50];
char npc_event[50];
int level;
int level2;
-} Atcmd_Binding;
+};
-struct Atcmd_Binding atcmd_binding[MAX_ATCMD_BINDINGS];
-struct Atcmd_Binding* get_atcommandbind_byname(const char* name);
+struct atcmd_binding_data** atcmd_binding;
+
+struct atcmd_binding_data* get_atcommandbind_byname(const char* name);
#endif /* _ATCOMMAND_H_ */
diff --git a/src/map/npc.c b/src/map/npc.c
index d629ac1b3..4faa54e24 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -2758,22 +2758,18 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c
struct script_state *st;
int i = 0, j = 0, k = 0;
char *temp;
- temp = (char*)aMalloc(strlen(message) + 1);
nullpo_ret(sd);
- if( ev == NULL || (nd = ev->nd) == NULL )
- {
+ if( ev == NULL || (nd = ev->nd) == NULL ) {
ShowError("npc_event: event not found [%s]\n", eventname);
return 0;
}
- if( sd->npc_id != 0 )
- { // Enqueue the event trigger.
+ if( sd->npc_id != 0 ) { // Enqueue the event trigger.
int i;
ARR_FIND( 0, MAX_EVENTQUEUE, i, sd->eventqueue[i][0] == '\0' );
- if( i < MAX_EVENTQUEUE )
- {
+ if( i < MAX_EVENTQUEUE ) {
safestrncpy(sd->eventqueue[i],eventname,50); //Event enqueued.
return 0;
}
@@ -2782,8 +2778,7 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c
return 1;
}
- if( ev->nd->sc.option&OPTION_INVISIBLE )
- { // Disabled npc, shouldn't trigger event.
+ if( ev->nd->sc.option&OPTION_INVISIBLE ) { // Disabled npc, shouldn't trigger event.
npc_event_dequeue(sd);
return 2;
}
@@ -2794,16 +2789,16 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c
// split atcmd parameters based on spaces
i = 0;
j = 0;
- while( message[i] != '\0' )
- {
- if( message[i] == ' ' && k < 127 )
- {
+
+ temp = (char*)aMalloc(strlen(message) + 1);
+
+ while( message[i] != '\0' ) {
+ if( message[i] == ' ' && k < 127 ) {
temp[j] = '\0';
setd_sub(st, NULL, ".@atcmd_parameters$", k++, (void *)temp, NULL);
j = 0;
++i;
- }
- else
+ } else
temp[j++] = message[i++];
}
diff --git a/src/map/script.c b/src/map/script.c
index 9521f2d54..6de233732 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -3956,14 +3956,14 @@ void script_setarray_pc(struct map_session_data* sd, const char* varname, uint8
/*==========================================
* I—¹
*------------------------------------------*/
-int do_final_script()
-{
+int do_final_script() {
+ int i;
#ifdef DEBUG_HASH
if (battle_config.etc_log)
{
FILE *fp = fopen("hash_dump.txt","wt");
if(fp) {
- int i,count[SCRIPT_HASH_SIZE];
+ int count[SCRIPT_HASH_SIZE];
int count2[SCRIPT_HASH_SIZE]; // number of buckets with a certain number of items
int n=0;
int min=INT_MAX,max=0,zero=0;
@@ -4033,6 +4033,13 @@ int do_final_script()
if (str_buf)
aFree(str_buf);
+ for( i = 0; i < atcmd_binding_count; i++ ) {
+ aFree(atcmd_binding[i]);
+ }
+
+ if( atcmd_binding_count != 0 )
+ aFree(atcmd_binding);
+
return 0;
}
/*==========================================
@@ -4050,12 +4057,20 @@ int do_init_script()
}
int script_reload() {
+ int i;
userfunc_db->clear(userfunc_db, db_script_free_code_sub);
db_clear(scriptlabel_db);
// @commands (script based)
// Clear bindings
- memset(atcmd_binding,0,sizeof(atcmd_binding));
+ for( i = 0; i < atcmd_binding_count; i++ ) {
+ aFree(atcmd_binding[i]);
+ }
+
+ if( atcmd_binding_count != 0 )
+ aFree(atcmd_binding);
+
+ atcmd_binding_count = 0;
if(sleep_db) {
struct linkdb_node *n = (struct linkdb_node *)sleep_db;
@@ -16355,52 +16370,90 @@ BUILDIN_FUNC(freeloop) {
/**
* @commands (script based)
**/
-BUILDIN_FUNC(bindatcmd)
-{
+BUILDIN_FUNC(bindatcmd) {
const char* atcmd;
const char* eventName;
- int i = 0, level = 0, level2 = 0;
-
+ int i, level = 0, level2 = 0;
+ bool create = false;
+
atcmd = script_getstr(st,2);
eventName = script_getstr(st,3);
+ if( *atcmd == atcommand_symbol || *atcmd == charcommand_symbol )
+ atcmd++;
+
if( script_hasdata(st,4) ) level = script_getnum(st,4);
if( script_hasdata(st,5) ) level2 = script_getnum(st,5);
- // check if event is already binded
- ARR_FIND(0, MAX_ATCMD_BINDINGS, i, strcmp(atcmd_binding[i].command,atcmd) == 0);
- if( i < MAX_ATCMD_BINDINGS )
- {
- safestrncpy(atcmd_binding[i].npc_event, eventName, 50);
- atcmd_binding[i].level = level;
- atcmd_binding[i].level2 = level2;
+ if( atcmd_binding_count == 0 ) {
+ CREATE(atcmd_binding,struct atcmd_binding_data*,1);
+
+ create = true;
+ } else {
+ ARR_FIND(0, atcmd_binding_count, i, strcmp(atcmd_binding[i]->command,atcmd) == 0);
+ if( i < atcmd_binding_count ) {/* update existent entry */
+ safestrncpy(atcmd_binding[i]->npc_event, eventName, 50);
+ atcmd_binding[i]->level = level;
+ atcmd_binding[i]->level2 = level2;
+ } else
+ create = true;
}
- else
- { // make new binding
- ARR_FIND(0, MAX_ATCMD_BINDINGS, i, atcmd_binding[i].command[0] == '\0');
- if( i < MAX_ATCMD_BINDINGS )
- {
- safestrncpy(atcmd_binding[i].command, atcmd, 50);
- safestrncpy(atcmd_binding[i].npc_event, eventName, 50);
- atcmd_binding[i].level = level;
- atcmd_binding[i].level2 = level2;
- }
+
+ if( create ) {
+ i = atcmd_binding_count;
+
+ if( atcmd_binding_count++ != 0 )
+ RECREATE(atcmd_binding,struct atcmd_binding_data*,atcmd_binding_count);
+
+ CREATE(atcmd_binding[i],struct atcmd_binding_data,1);
+
+ safestrncpy(atcmd_binding[i]->command, atcmd, 50);
+ safestrncpy(atcmd_binding[i]->npc_event, eventName, 50);
+ atcmd_binding[i]->level = level;
+ atcmd_binding[i]->level2 = level2;
}
-
+
return 0;
}
-BUILDIN_FUNC(unbindatcmd)
-{
+BUILDIN_FUNC(unbindatcmd) {
const char* atcmd;
int i = 0;
atcmd = script_getstr(st, 2);
- ARR_FIND(0, MAX_ATCMD_BINDINGS, i, strcmp(atcmd_binding[i].command, atcmd) == 0);
- if( i < MAX_ATCMD_BINDINGS )
- memset(&atcmd_binding[i],0,sizeof(atcmd_binding[0]));
+ if( *atcmd == atcommand_symbol || *atcmd == charcommand_symbol )
+ atcmd++;
+
+ if( atcmd_binding_count == 0 ) {
+ script_pushint(st, 0);
+ return 0;
+ }
+
+ ARR_FIND(0, atcmd_binding_count, i, strcmp(atcmd_binding[i]->command, atcmd) == 0);
+ if( i < atcmd_binding_count ) {
+ int cursor = 0;
+ aFree(atcmd_binding[i]);
+ atcmd_binding[i] = NULL;
+ /* compact the list now that we freed a slot somewhere */
+ for( i = 0, cursor = 0; i < atcmd_binding_count; i++ ) {
+ if( atcmd_binding[i] == NULL )
+ continue;
+
+ if( cursor != i ) {
+ memmove(&atcmd_binding[cursor], &atcmd_binding[i], sizeof(struct atcmd_binding_data*));
+ }
+
+ cursor++;
+ }
+ if( (atcmd_binding_count = cursor) == 0 )
+ aFree(atcmd_binding);
+
+ script_pushint(st, 1);
+ } else
+ script_pushint(st, 0);/* not found */
+
return 0;
}