diff options
-rw-r--r-- | Changelog-Trunk.txt | 4 | ||||
-rw-r--r-- | src/char/char.c | 73 | ||||
-rw-r--r-- | src/char_sql/char.c | 71 | ||||
-rw-r--r-- | src/common/db.h | 77 | ||||
-rw-r--r-- | src/common/strlib.c | 19 | ||||
-rw-r--r-- | src/common/strlib.h | 9 | ||||
-rw-r--r-- | src/map/script.c | 68 |
7 files changed, 213 insertions, 108 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index d8e515016..179add4a1 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -3,6 +3,10 @@ Date Added AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK. IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. +2007/06/02 + * Displaying op names instead of numbers in script engine errors. + * Fixed a bug introduced in the last rework of the fame ranking. + * Created safestrncpy that ensures the string is nul-terminated. [FlavioJS] 2007/06/01 * Updated sql files [Playtester] * Fixed ircbot not processing new users diff --git a/src/char/char.c b/src/char/char.c index 8ef7eaddd..ac3c1a1b2 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -3123,7 +3123,9 @@ int parse_frommap(int fd) char type = RFIFOB(fd, 10); int size; struct fame_list* list; - + int player_pos; + int fame_pos; + switch(type) { case 1: size = fame_list_size_smith; list = smith_fame_list; break; @@ -3131,56 +3133,33 @@ int parse_frommap(int fd) case 3: size = fame_list_size_taekwon; list = taekwon_fame_list; break; default: size = 0; list = NULL; break; } - if( size == 0 ) - {// No list - RFIFOSKIP(fd,11); - break; + + ARR_FIND(0, size, player_pos, list[player_pos].id == cid); + ARR_FIND(0, size, fame_pos, list[fame_pos].fame <= fame); + + if( player_pos == size && fame_pos == size ) + ;// not on list and not enough fame to get on it + else if( fame_pos == player_pos ) + {// same position + list[player_pos].fame = fame; + char_update_fame_list(type, player_pos, fame); } - for( i = 0; i < size; ++i ) - { - if( list[i].id != cid ) - continue; - // player found, update position - if( i > 0 && fame >= list[i - 1].fame ) - {// moved up - struct fame_list entry; - int t; - for( t = 0; fame < list[t].fame ; ++t ) - ;// get target position (always < i) - memcpy(&entry, &list[i], sizeof(struct fame_list)); - entry.fame = fame; - memmove(&list[t + 1], &list[t], (t - i)*sizeof(struct fame_list)); - memcpy(&list[t], &entry, sizeof(struct fame_list)); - char_send_fame_list(-1); - } - else if( i < size - 1 && fame < list[i + 1].fame ) - {// moved down - always stays in the list - struct fame_list entry; - int t; - for( t = i + 2; t < size && fame < list[t].fame ; ++t ) - ;// get target position - --t; - memcpy(&entry, &list[i], sizeof(struct fame_list)); - entry.fame = fame; - memmove(&list[i], &list[i + 1], (t - i)*sizeof(struct fame_list)); - memcpy(&list[t], &entry, sizeof(struct fame_list)); - char_send_fame_list(-1); + else + {// move in the list + if( player_pos == size ) + {// new ranker - not in the list + ARR_MOVE(size - 1, fame_pos, list, struct fame_list); + list[fame_pos].id = cid; + list[fame_pos].fame = fame; + char_loadName(cid, list[fame_pos].name); } else - {// same position - list[i].fame = fame; - char_update_fame_list(type, i, fame); + {// already in the list + if( fame_pos == size ) + --fame_pos;// move to the end of the list + ARR_MOVE(player_pos, fame_pos, list, struct fame_list); + list[fame_pos].fame = fame; } - break; - } - - if( i == size && fame >= list[size - 1].fame ) - {// not on list and has enough fame - for( i = 0; fame < list[i].fame; ++i ) - ;// get target position - list[i].id = cid; - list[i].fame = fame; - char_loadName(list[i].id, list[i].name); char_send_fame_list(-1); } diff --git a/src/char_sql/char.c b/src/char_sql/char.c index 9929be3a7..7cf41eec9 100644 --- a/src/char_sql/char.c +++ b/src/char_sql/char.c @@ -2822,6 +2822,8 @@ int parse_frommap(int fd) char type = RFIFOB(fd, 10); int size; struct fame_list* list; + int player_pos; + int fame_pos; switch(type) { @@ -2830,56 +2832,33 @@ int parse_frommap(int fd) case 3: size = fame_list_size_taekwon; list = taekwon_fame_list; break; default: size = 0; list = NULL; break; } - if( size == 0 ) - {// No list - RFIFOSKIP(fd,11); - break; + + ARR_FIND(0, size, player_pos, list[player_pos].id == cid); + ARR_FIND(0, size, fame_pos, list[fame_pos].fame <= fame); + + if( player_pos == size && fame_pos == size ) + ;// not on list and not enough fame to get on it + else if( fame_pos == player_pos ) + {// same position + list[player_pos].fame = fame; + char_update_fame_list(type, player_pos, fame); } - for( i = 0; i < size; ++i ) - { - if( list[i].id != cid ) - continue; - // player found, update position - if( i > 0 && fame >= list[i - 1].fame ) - {// moved up - struct fame_list entry; - int t; - for( t = 0; fame < list[t].fame ; ++t ) - ;// get target position (always < i) - memcpy(&entry, &list[i], sizeof(struct fame_list)); - entry.fame = fame; - memmove(&list[t + 1], &list[t], (t - i)*sizeof(struct fame_list)); - memcpy(&list[t], &entry, sizeof(struct fame_list)); - char_send_fame_list(-1); - } - else if( i < size - 1 && fame < list[i + 1].fame ) - {// moved down - always stays in the list - struct fame_list entry; - int t; - for( t = i + 2; t < size && fame < list[t].fame ; ++t ) - ;// get target position - --t; - memcpy(&entry, &list[i], sizeof(struct fame_list)); - entry.fame = fame; - memmove(&list[i], &list[i + 1], (t - i)*sizeof(struct fame_list)); - memcpy(&list[t], &entry, sizeof(struct fame_list)); - char_send_fame_list(-1); + else + {// move in the list + if( player_pos == size ) + {// new ranker - not in the list + ARR_MOVE(size - 1, fame_pos, list, struct fame_list); + list[fame_pos].id = cid; + list[fame_pos].fame = fame; + char_loadName(cid, list[fame_pos].name); } else - {// same position - list[i].fame = fame; - char_update_fame_list(type, i, fame); + {// already in the list + if( fame_pos == size ) + --fame_pos;// move to the end of the list + ARR_MOVE(player_pos, fame_pos, list, struct fame_list); + list[fame_pos].fame = fame; } - break; - } - - if( i == size && fame >= list[size - 1].fame ) - {// not on list and has enough fame - for( i = 0; fame < list[i].fame; ++i ) - ;// get target position - list[i].id = cid; - list[i].fame = fame; - char_loadName(list[i].id, list[i].name); char_send_fame_list(-1); } diff --git a/src/common/db.h b/src/common/db.h index 992469f66..5c7d42d87 100644 --- a/src/common/db.h +++ b/src/common/db.h @@ -691,4 +691,81 @@ void* linkdb_search ( struct linkdb_node** head, void *key); void* linkdb_erase ( struct linkdb_node** head, void *key); void linkdb_final ( struct linkdb_node** head ); + + +/// Finds an entry in an array. +/// ex: ARR_FIND(0, size, i, list[i] == target); +/// +/// @param __start Starting index (ex: 0) +/// @param __end End index (ex: size of the array) +/// @param __var Index variable +/// @param __cmp Expression that returns true when the target entry is found +#define ARR_FIND(__start, __end, __var, __cmp) \ + do{ \ + for( (__var) = (__start); (__var) < (__end); ++(__var) ) \ + if( __cmp ) \ + break; \ + }while(0) + + + +/// Moves an entry of the array. +/// Use ARR_MOVERIGHT/ARR_MOVELEFT if __from and __to are direct numbers. +/// ex: ARR_MOVE(i, 0, list, int);// move index i to index 0 +/// +/// +/// @param __from Initial index of the entry +/// @param __end Target index of the entry +/// @param __arr Array +/// @param __type Type of entry +#define ARR_MOVE(__from, __to, __arr, __type) \ + do{ \ + if( (__from) != (__to) ) \ + { \ + __type __backup__; \ + memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \ + if( (__from) < (__to) ) \ + memmove((__arr)+(__from), (__arr)+(__from)+1, ((__to)-(__from))*sizeof(__type)); \ + else if( (__from) > (__to) ) \ + memmove((__arr)+(__to)+1, (__arr)+(__to), ((__from)-(__to))*sizeof(__type)); \ + memmove((__arr)+(__to), &__backup__, sizeof(__type)); \ + } \ + }while(0) + + + +/// Moves an entry of the array to the right. +/// ex: ARR_MOVERIGHT(1, 4, list, int);// move index 1 to index 4 +/// +/// @param __from Initial index of the entry +/// @param __end Target index of the entry +/// @param __arr Array +/// @param __type Type of entry +#define ARR_MOVERIGHT(__from, __to, __arr, __type) \ + do{ \ + __type __backup__; \ + memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \ + memmove((__arr)+(__from), (__arr)+(__from)+1, ((__to)-(__from))*sizeof(__type)); \ + memmove((__arr)+(__to), &__backup__, sizeof(__type)); \ + }while(0) + + + +/// Moves an entry of the array to the left. +/// ex: ARR_MOVELEFT(3, 0, list, int);// move index 3 to index 0 +/// +/// @param __from Initial index of the entry +/// @param __end Target index of the entry +/// @param __arr Array +/// @param __type Type of entry +#define ARR_MOVELEFT(__from, __to, __arr, __type) \ + do{ \ + __type __backup__; \ + memmove(&__backup__, (__arr)+(__from), sizeof(__type)); \ + memmove((__arr)+(__to)+1, (__arr)+(__to), ((__from)-(__to))*sizeof(__type)); \ + memmove((__arr)+(__to), &__backup__, sizeof(__type)); \ + }while(0) + + + #endif /* _DB_H_ */ diff --git a/src/common/strlib.c b/src/common/strlib.c index 977dc8306..a683dc100 100644 --- a/src/common/strlib.c +++ b/src/common/strlib.c @@ -1,14 +1,15 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder +#include "../common/cbasetypes.h" +#include "../common/malloc.h" +#include "../common/utils.h" +#include "strlib.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "strlib.h" -#include "../common/cbasetypes.h" -#include "../common/utils.h" -#include "../common/malloc.h" #define J_MAX_MALLOC_SIZE 65535 @@ -299,3 +300,13 @@ int config_switch(const char* str) return (int)strtol(str, NULL, 0); } + +/// always nul-terminates the string +char* safestrncpy(char* dst, const char* src, size_t n) +{ + char* ret; + ret = strncpy(dst, src, n); + if( ret != NULL ) + ret[n - 1] = '\0'; + return ret; +} diff --git a/src/common/strlib.h b/src/common/strlib.h index a3753b918..42fb75ab2 100644 --- a/src/common/strlib.h +++ b/src/common/strlib.h @@ -4,7 +4,9 @@ #ifndef _STRLIB_H_ #define _STRLIB_H_ -#include <stddef.h> // size_t +#ifndef _CBASETYPES_H_ +#include "../common/cbasetypes.h" +#endif char* jstrescape (char* pt); char* jstrescapecpy (char* pt, const char* spt); @@ -15,7 +17,7 @@ char* trim(char* str); char* normalize_name(char* str,const char* delims); const char *stristr(const char *haystack, const char *needle); -#ifdef __WIN32 +#ifdef WIN32 #define HAVE_STRTOK_R #define strtok_r(s,delim,save_ptr) _strtok_r((s),(delim),(save_ptr)) char* _strtok_r(char* s1, const char* s2, char** lasts); @@ -28,4 +30,7 @@ size_t strnlen (const char* string, size_t maxlen); int e_mail_check(char* email); int config_switch(const char* str); +/// always nul-terminates the string +char* safestrncpy(char* dst, const char* src, size_t n); + #endif /* _STRLIB_H_ */ diff --git a/src/map/script.c b/src/map/script.c index e2395aab4..f97fbc869 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -314,6 +314,56 @@ enum { MF_GUILDLOCK }; +const char* script_op2name(int op) +{ +#define RETURN_OP_NAME(type) case type: return #type + switch( op ) + { + RETURN_OP_NAME(C_NOP); + RETURN_OP_NAME(C_POS); + RETURN_OP_NAME(C_INT); + RETURN_OP_NAME(C_PARAM); + RETURN_OP_NAME(C_FUNC); + RETURN_OP_NAME(C_STR); + RETURN_OP_NAME(C_CONSTSTR); + RETURN_OP_NAME(C_ARG); + RETURN_OP_NAME(C_NAME); + RETURN_OP_NAME(C_EOL); + RETURN_OP_NAME(C_RETINFO); + RETURN_OP_NAME(C_USERFUNC); + RETURN_OP_NAME(C_USERFUNC_POS); + + // operators + RETURN_OP_NAME(C_OP3); + RETURN_OP_NAME(C_LOR); + RETURN_OP_NAME(C_LAND); + RETURN_OP_NAME(C_LE); + RETURN_OP_NAME(C_LT); + RETURN_OP_NAME(C_GE); + RETURN_OP_NAME(C_GT); + RETURN_OP_NAME(C_EQ); + RETURN_OP_NAME(C_NE); + RETURN_OP_NAME(C_XOR); + RETURN_OP_NAME(C_OR); + RETURN_OP_NAME(C_AND); + RETURN_OP_NAME(C_ADD); + RETURN_OP_NAME(C_SUB); + RETURN_OP_NAME(C_MUL); + RETURN_OP_NAME(C_DIV); + RETURN_OP_NAME(C_MOD); + RETURN_OP_NAME(C_NEG); + RETURN_OP_NAME(C_LNOT); + RETURN_OP_NAME(C_NOT); + RETURN_OP_NAME(C_R_SHIFT); + RETURN_OP_NAME(C_L_SHIFT); + + default: + ShowDebug("script_op2name: unexpected op=%d\n", op); + return "???"; + } +#undef RETURN_OP_NAME +} + //Reports on the console the src of a script error. static void report_src(struct script_state *st) { @@ -2392,7 +2442,7 @@ void op_3(struct script_state* st, int op) flag = data->u.num; else { - ShowError("script:op_3: invalid type of data op:%d data:%d\n", op, data->type); + ShowError("script:op_3: invalid type of data op:%s data:%s\n", script_op2name(op), script_op2name(data->type)); report_src(st); script_removetop(st, -3, 0); script_pushnil(st); @@ -2433,7 +2483,7 @@ void op_2str(struct script_state* st, int op, const char* s1, const char* s2) return; } default: - ShowError("script:op2_str: unexpected string operator op:%d\n", op); + ShowError("script:op2_str: unexpected string operator op:%s\n", script_op2name(op)); report_src(st); script_pushnil(st); st->state = END; @@ -2469,7 +2519,7 @@ void op_2num(struct script_state* st, int op, int i1, int i2) case C_MOD: if( i2 == 0 ) { - ShowError("script:op_2num: division by zero detected op:%d\n", op); + ShowError("script:op_2num: division by zero detected op:%s\n", script_op2name(op)); report_src(st); script_pushnil(st); st->state = END; @@ -2487,20 +2537,20 @@ void op_2num(struct script_state* st, int op, int i1, int i2) case C_SUB: ret = i1 - i2; ret_double = (double)i1 - (double)i2; break; case C_MUL: ret = i1 * i2; ret_double = (double)i1 * (double)i2; break; default: - ShowError("script:op_2num: unexpected number operator op:%d\n", op); + ShowError("script:op_2num: unexpected number operator op:%s\n", script_op2name(op)); report_src(st); script_pushnil(st); return; } if( ret_double < INT_MIN ) { - ShowWarning("script:op_2num: underflow detected op:%d\n", op); + ShowWarning("script:op_2num: underflow detected op:%s\n", script_op2name(op)); report_src(st); ret = INT_MIN; } else if( ret_double > INT_MAX ) { - ShowWarning("script:op_2num: overflow detected op:%d\n", op); + ShowWarning("script:op_2num: overflow detected op:%s\n", script_op2name(op)); report_src(st); ret = INT_MAX; } @@ -2546,7 +2596,7 @@ void op_2(struct script_state *st, int op) } else {// invalid argument - ShowError("script:op_2: invalid type of data op:%d left:%d right:%d\n", op, left->type, right->type); + ShowError("script:op_2: invalid type of data op:%s left:%s right:%s\n", script_op2name(op), script_op2name(left->type), script_op2name(right->type)); report_src(st); script_removetop(st, -2, 0); script_pushnil(st); @@ -2568,7 +2618,7 @@ void op_1(struct script_state* st, int op) if( !data_isint(data) ) {// not a number - ShowError("script:op_1: invalid type of data op:%d data:%d\n", op, data->type); + ShowError("script:op_1: invalid type of data op:%s data:%s\n", script_op2name(op), script_op2name(data->type)); report_src(st); script_pushnil(st); st->state = END; @@ -2583,7 +2633,7 @@ void op_1(struct script_state* st, int op) case C_NOT: i1 = ~i1; break; case C_LNOT: i1 = !i1; break; default: - ShowError("script:op_1: unexpected operator op:%d\n", op); + ShowError("script:op_1: unexpected operator op:%s\n", script_op2name(op)); report_src(st); script_pushnil(st); st->state = END; |