diff options
Diffstat (limited to 'src')
88 files changed, 2572 insertions, 1020 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 000000000..0bf5b0eb6 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,9 @@ + +add_subdirectory( common ) +add_subdirectory( login ) +add_subdirectory( char ) +add_subdirectory( char_sql ) +add_subdirectory( map ) +add_subdirectory( tool ) +#add_subdirectory( txt-converter ) +#add_subdirectory( plugins ) diff --git a/src/char/CMakeLists.txt b/src/char/CMakeLists.txt new file mode 100644 index 000000000..9e0cbd9f4 --- /dev/null +++ b/src/char/CMakeLists.txt @@ -0,0 +1,51 @@ + +# +# char txt +# +if( HAVE_common_base ) +message( STATUS "Creating target char-server" ) +set( TXT_CHAR_HEADERS + "${CMAKE_CURRENT_SOURCE_DIR}/char.h" + "${CMAKE_CURRENT_SOURCE_DIR}/int_guild.h" + "${CMAKE_CURRENT_SOURCE_DIR}/int_homun.h" + "${CMAKE_CURRENT_SOURCE_DIR}/int_party.h" + "${CMAKE_CURRENT_SOURCE_DIR}/int_pet.h" + "${CMAKE_CURRENT_SOURCE_DIR}/int_status.h" + "${CMAKE_CURRENT_SOURCE_DIR}/int_storage.h" + "${CMAKE_CURRENT_SOURCE_DIR}/inter.h" + ) +set( TXT_CHAR_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/char.c" + "${CMAKE_CURRENT_SOURCE_DIR}/int_guild.c" + "${CMAKE_CURRENT_SOURCE_DIR}/int_homun.c" + "${CMAKE_CURRENT_SOURCE_DIR}/int_party.c" + "${CMAKE_CURRENT_SOURCE_DIR}/int_pet.c" + "${CMAKE_CURRENT_SOURCE_DIR}/int_status.c" + "${CMAKE_CURRENT_SOURCE_DIR}/int_storage.c" + "${CMAKE_CURRENT_SOURCE_DIR}/inter.c" + ) +set( DEPENDENCIES common_base ) +set( LIBRARIES ${GLOBAL_LIBRARIES} ) +set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ) +set( DEFINITIONS ${GLOBAL_DEFINITIONS} TXT_ONLY ) +set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${TXT_CHAR_HEADERS} ${TXT_CHAR_SOURCES} ) +source_group( common FILES ${COMMON_BASE_HEADERS} ) +source_group( char FILES ${TXT_CHAR_HEADERS} ${TXT_CHAR_SOURCES} ) +include_directories( ${INCLUDE_DIRS} ) +add_executable( char-server ${SOURCE_FILES} ) +add_dependencies( char-server ${DEPENDENCIES} ) +target_link_libraries( char-server ${LIBRARIES} ${DEPENDENCIES} ) +set_target_properties( char-server PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" ) +if( WITH_COMPONENT_RUNTIME ) + cpack_add_component( Runtime_charserver_txt DESCRIPTION "char-server (txt version)" DISPLAY_NAME "char-server" GROUP Runtime ) + install( TARGETS char-server + DESTINATION "." + COMPONENT Runtime_charserver_txt ) +endif() +message( STATUS "Creating target char-server - done" ) +set( HAVE_char-server ON CACHE BOOL "char-server target is available" ) +mark_as_advanced( HAVE_char-server ) +else() +message( STATUS "Skipping target char-server (requires common_base)" ) +unset( HAVE_char-server CACHE ) +endif() diff --git a/src/char/Makefile.in b/src/char/Makefile.in index 359e19b01..ba8f4fe64 100644 --- a/src/char/Makefile.in +++ b/src/char/Makefile.in @@ -3,12 +3,16 @@ COMMON_OBJ = ../common/obj_all/core.o ../common/obj_all/socket.o ../common/obj_a ../common/obj_all/db.o ../common/obj_all/plugins.o ../common/obj_all/lock.o \ ../common/obj_all/malloc.o ../common/obj_all/showmsg.o ../common/obj_all/utils.o \ ../common/obj_all/strlib.o ../common/obj_all/grfio.o \ - ../common/obj_all/mapindex.o ../common/obj_all/ers.o + ../common/obj_all/mapindex.o ../common/obj_all/ers.o ../common/obj_all/random.o COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \ ../common/version.h ../common/db.h ../common/plugins.h ../common/lock.h \ ../common/malloc.h ../common/showmsg.h ../common/utils.h \ ../common/strlib.h ../common/grfio.h \ - ../common/mapindex.h ../common/ers.h + ../common/mapindex.h ../common/ers.h ../common/random.h + +MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o +MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h +MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar CHAR_OBJ = obj_txt/char.o obj_txt/inter.o obj_txt/int_party.o obj_txt/int_guild.o \ obj_txt/int_storage.o obj_txt/int_status.o obj_txt/int_pet.o obj_txt/int_homun.o @@ -21,8 +25,8 @@ CHAR_H = char.h inter.h int_party.h int_guild.h int_storage.h int_status.h int_p all: char-server -char-server: obj_txt $(CHAR_OBJ) $(COMMON_OBJ) - @CC@ @LDFLAGS@ -o ../../char-server@EXEEXT@ $(CHAR_OBJ) $(COMMON_OBJ) @LIBS@ +char-server: obj_txt $(CHAR_OBJ) $(COMMON_OBJ) $(MT19937AR_OBJ) + @CC@ @LDFLAGS@ -o ../../char-server@EXEEXT@ $(CHAR_OBJ) $(COMMON_OBJ) $(MT19937AR_OBJ) @LIBS@ clean: rm -rf *.o obj_txt ../../char-server@EXEEXT@ @@ -39,9 +43,12 @@ help: obj_txt: -mkdir obj_txt -obj_txt/%.o: %.c $(CHAR_H) $(COMMON_H) - @CC@ @CFLAGS@ -DTXT_ONLY @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_txt/%.o: %.c $(CHAR_H) $(COMMON_H) $(MT19937AR_H) + @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) -DTXT_ONLY @CPPFLAGS@ -c $(OUTPUT_OPTION) $< -# missing common object files +# missing object files ../common/obj_all/%.o: @$(MAKE) -C ../common txt + +MT19937AR_OBJ: + @$(MAKE) -C ../../3rdparty/mt19937ar diff --git a/src/char/char.c b/src/char/char.c index 6599a6258..617e3d10c 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -176,7 +176,7 @@ struct online_char_data { }; static DBMap* online_char_db; // int account_id -> struct online_char_data* -static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr data); +static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data); static void* create_online_char_data(DBKey key, va_list args) { @@ -571,8 +571,8 @@ int mmo_char_tostr(char *str, struct mmo_charstatus *p, struct global_reg *reg, *(str_p++) = '\t'; for(i = 0; i < MAX_SKILL; i++) - if (p->skill[i].id && p->skill[i].flag != 1) { - str_p += sprintf(str_p, "%d,%d ", p->skill[i].id, (p->skill[i].flag == 0) ? p->skill[i].lv : p->skill[i].flag-2); + if (p->skill[i].id != 0 && p->skill[i].flag != SKILL_FLAG_TEMPORARY) { + str_p += sprintf(str_p, "%d,%d ", p->skill[i].id, (p->skill[i].flag == SKILL_FLAG_PERMANENT) ? p->skill[i].lv : p->skill[i].flag - SKILL_FLAG_REPLACED_LV_0); } *(str_p++) = '\t'; @@ -1229,7 +1229,7 @@ void mmo_char_sync(void) //---------------------------------------------------- // Function to save (in a periodic way) datas in files //---------------------------------------------------- -int mmo_char_sync_timer(int tid, unsigned int tick, int id, intptr data) +int mmo_char_sync_timer(int tid, unsigned int tick, int id, intptr_t data) { if (save_log) ShowInfo("Saving all files...\n"); @@ -1782,7 +1782,7 @@ int count_users(void) int i, users; users = 0; - for(i = 0; i < MAX_MAP_SERVERS; i++) { + for(i = 0; i < ARRAYLENGTH(server); i++) { if (server[i].fd > 0) { users += server[i].users; } @@ -2060,24 +2060,74 @@ static void char_auth_ok(int fd, struct char_session_data *sd) // continues when account data is received... } -int send_accounts_tologin(int tid, unsigned int tick, int id, intptr data); +int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data); +void mapif_server_reset(int id); + + +/// Resets all the data. +void loginif_reset(void) +{ + int id; + // TODO kick everyone out and reset everything or wait for connect and try to reaquire locks [FlavioJS] + for( id = 0; id < ARRAYLENGTH(server); ++id ) + mapif_server_reset(id); + flush_fifos(); + exit(EXIT_FAILURE); +} + + +/// Checks the conditions for the server to stop. +/// If all the conditions are met, it stops the core loop. +void loginif_check_shutdown(void) +{ + if( runflag != CHARSERVER_ST_SHUTDOWN ) + return; + runflag = CORE_ST_STOP; +} + + +/// Called when the connection to Login Server is disconnected. +void loginif_on_disconnect(void) +{ + ShowWarning("Connection to Login Server lost.\n\n"); +} + + +/// Called when all the connection steps are completed. +void loginif_on_ready(void) +{ + int i; + + loginif_check_shutdown(); + + //Send online accounts to login server. + send_accounts_tologin(INVALID_TIMER, gettick(), 0, 0); + + // if no map-server already connected, display a message... + ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd > 0 && server[i].map[0] ); + if( i == ARRAYLENGTH(server) ) + ShowStatus("Awaiting maps from map-server.\n"); +} + int parse_fromlogin(int fd) { + struct char_session_data* sd = NULL; int i; - struct char_session_data *sd; - // only login-server can have an access to here. - // so, if it isn't the login-server, we disconnect the session. + // only process data from the login-server if( fd != login_fd ) - set_eof(fd); + { + ShowDebug("parse_fromlogin: Disconnecting invalid session #%d (is not the login-server)\n", fd); + do_close(fd); + return 0; + } - if(session[fd]->flag.eof) { - if (fd == login_fd) { - ShowWarning("Connection to login-server lost (connection #%d).\n", fd); - login_fd = -1; - } + if( session[fd]->flag.eof ) + { do_close(fd); + login_fd = -1; + loginif_on_disconnect(); return 0; } @@ -2101,16 +2151,11 @@ int parse_fromlogin(int fd) ShowError("The server communication passwords (default s1/p1) are probably invalid.\n"); ShowError("Also, please make sure your accounts file (default: accounts.txt) has the correct communication username/passwords and the gender of the account is S.\n"); ShowError("The communication passwords are set in map_athena.conf and char_athena.conf\n"); + set_eof(fd); + return 0; } else { ShowStatus("Connected to login-server (connection #%d).\n", fd); - - //Send online accounts to login server. - send_accounts_tologin(INVALID_TIMER, gettick(), 0, 0); - - // if no map-server already connected, display a message... - ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd > 0 && server[i].map[0] ); - if( i == MAX_MAP_SERVERS ) - ShowStatus("Awaiting maps from map-server.\n"); + loginif_on_ready(); } RFIFOSKIP(fd,3); break; @@ -2226,7 +2271,7 @@ int parse_fromlogin(int fd) } // remove specifical skills of classes 19, 4020 and 4042 for(j = 315; j <= 322; j++) { - if (char_dat[i].status.skill[j].id > 0 && !char_dat[i].status.skill[j].flag) { + if (char_dat[i].status.skill[j].id > 0 && char_dat[i].status.skill[j].flag == SKILL_FLAG_PERMANENT) { char_dat[i].status.skill_point += char_dat[i].status.skill[j].lv; char_dat[i].status.skill[j].id = 0; char_dat[i].status.skill[j].lv = 0; @@ -2234,7 +2279,7 @@ int parse_fromlogin(int fd) } // remove specifical skills of classes 20, 4021 and 4043 for(j = 323; j <= 330; j++) { - if (char_dat[i].status.skill[j].id > 0 && !char_dat[i].status.skill[j].flag) { + if (char_dat[i].status.skill[j].id > 0 && char_dat[i].status.skill[j].flag == SKILL_FLAG_PERMANENT) { char_dat[i].status.skill_point += char_dat[i].status.skill[j].lv; char_dat[i].status.skill[j].id = 0; char_dat[i].status.skill[j].lv = 0; @@ -2377,6 +2422,34 @@ int parse_fromlogin(int fd) return 0; } +int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data); +int ping_login_server(int tid, unsigned int tick, int id, intptr_t data); +int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data); + +void do_init_loginif(void) +{ + // establish char-login connection if not present + add_timer_func_list(check_connect_login_server, "check_connect_login_server"); + add_timer_interval(gettick() + 1000, check_connect_login_server, 0, 0, 10 * 1000); + + // keep the char-login connection alive + add_timer_func_list(ping_login_server, "ping_login_server"); + add_timer_interval(gettick() + 1000, ping_login_server, 0, 0, ((int)stall_time-2) * 1000); + + // send a list of all online account IDs to login server + add_timer_func_list(send_accounts_tologin, "send_accounts_tologin"); + add_timer_interval(gettick() + 1000, send_accounts_tologin, 0, 0, 3600 * 1000); //Sync online accounts every hour +} + +void do_final_loginif(void) +{ + if( login_fd != -1 ) + { + do_close(login_fd); + login_fd = -1; + } +} + int request_accreg2(int account_id, int char_id) { if (login_fd > 0) { @@ -2592,36 +2665,76 @@ int char_loadName(int char_id, char* name) int search_mapserver(unsigned short map, uint32 ip, uint16 port); + +/// Initializes a server structure. +void mapif_server_init(int id) +{ + memset(&server[id], 0, sizeof(server[id])); + server[id].fd = -1; +} + + +/// Destroys a server structure. +void mapif_server_destroy(int id) +{ + if( server[id].fd == -1 ) + { + do_close(server[id].fd); + server[id].fd = -1; + } +} + + +/// Resets all the data related to a server. +void mapif_server_reset(int id) +{ + int i,j; + unsigned char buf[16384]; + int fd = server[id].fd; + //Notify other map servers that this one is gone. [Skotlex] + WBUFW(buf,0) = 0x2b20; + WBUFL(buf,4) = htonl(server[id].ip); + WBUFW(buf,8) = htons(server[id].port); + j = 0; + for(i = 0; i < MAX_MAP_PER_SERVER; i++) + if (server[id].map[i]) + WBUFW(buf,10+(j++)*4) = server[id].map[i]; + if (j > 0) { + WBUFW(buf,2) = j * 4 + 10; + mapif_sendallwos(fd, buf, WBUFW(buf,2)); + } + online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server. + create_online_files(); + mapif_server_destroy(id); + mapif_server_init(id); +} + + +/// Called when the connection to a Map Server is disconnected. +void mapif_on_disconnect(int id) +{ + ShowStatus("Map-server #%d has disconnected.\n", id); + mapif_server_reset(id); +} + + int parse_frommap(int fd) { int i, j; int id; - ARR_FIND( 0, MAX_MAP_SERVERS, id, server[id].fd == fd ); - if(id == MAX_MAP_SERVERS) - set_eof(fd); - if(session[fd]->flag.eof) { - if (id < MAX_MAP_SERVERS) { - unsigned char buf[16384]; - ShowStatus("Map-server %d (session #%d) has disconnected.\n", id, fd); - //Notify other map servers that this one is gone. [Skotlex] - WBUFW(buf,0) = 0x2b20; - WBUFL(buf,4) = htonl(server[id].ip); - WBUFW(buf,8) = htons(server[id].port); - j = 0; - for(i = 0; i < MAX_MAP_PER_SERVER; i++) - if (server[id].map[i]) - WBUFW(buf,10+(j++)*4) = server[id].map[i]; - if (j > 0) { - WBUFW(buf,2) = j * 4 + 10; - mapif_sendallwos(fd, buf, WBUFW(buf,2)); - } - memset(&server[id], 0, sizeof(struct mmo_map_server)); - server[id].fd = -1; - online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server. - } + ARR_FIND( 0, ARRAYLENGTH(server), id, server[id].fd == fd ); + if( id == ARRAYLENGTH(server) ) + {// not a map server + ShowDebug("parse_frommap: Disconnecting invalid session #%d (is not a map-server)\n", fd); do_close(fd); - create_online_files(); + return 0; + } + if( session[fd]->flag.eof ) + { + do_close(fd); + server[id].fd = -1; + mapif_on_disconnect(id); return 0; } @@ -2672,14 +2785,14 @@ int parse_frommap(int fd) mapif_sendallwos(fd, buf, WBUFW(buf,2)); } // Transmitting the maps of the other map-servers to the new map-server - for(x = 0; x < MAX_MAP_SERVERS; x++) { + for(x = 0; x < ARRAYLENGTH(server); x++) { if (server[x].fd > 0 && x != id) { - WFIFOHEAD(fd,10 +4*MAX_MAP_PER_SERVER); + WFIFOHEAD(fd,10 +4*ARRAYLENGTH(server)); WFIFOW(fd,0) = 0x2b04; WFIFOL(fd,4) = htonl(server[x].ip); WFIFOW(fd,8) = htons(server[x].port); j = 0; - for(i = 0; i < MAX_MAP_PER_SERVER; i++) + for(i = 0; i < ARRAYLENGTH(server); i++) if (server[x].map[i]) WFIFOW(fd,10+(j++)*4) = server[x].map[i]; if (j > 0) { @@ -2802,26 +2915,37 @@ int parse_frommap(int fd) uint32 ip = RFIFOL(fd,14); RFIFOSKIP(fd,18); - // create temporary auth entry - CREATE(node, struct auth_node, 1); - node->account_id = account_id; - node->char_id = 0; - node->login_id1 = login_id1; - node->login_id2 = login_id2; - //node->sex = 0; - node->ip = ntohl(ip); - //node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server) - //node->gmlevel = 0; - idb_put(auth_db, account_id, node); - - //Set char to "@ char select" in online db [Kevin] - set_char_charselect(account_id); - - WFIFOHEAD(fd,7); - WFIFOW(fd,0) = 0x2b03; - WFIFOL(fd,2) = account_id; - WFIFOB(fd,6) = 0; - WFIFOSET(fd,7); + if( runflag != CHARSERVER_ST_RUNNING ) + { + WFIFOHEAD(fd,7); + WFIFOW(fd,0) = 0x2b03; + WFIFOL(fd,2) = account_id; + WFIFOB(fd,6) = 0;// not ok + WFIFOSET(fd,7); + } + else + { + // create temporary auth entry + CREATE(node, struct auth_node, 1); + node->account_id = account_id; + node->char_id = 0; + node->login_id1 = login_id1; + node->login_id2 = login_id2; + //node->sex = 0; + node->ip = ntohl(ip); + //node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server) + //node->gmlevel = 0; + idb_put(auth_db, account_id, node); + + //Set char to "@ char select" in online db [Kevin] + set_char_charselect(account_id); + + WFIFOHEAD(fd,7); + WFIFOW(fd,0) = 0x2b03; + WFIFOL(fd,2) = account_id; + WFIFOB(fd,6) = 1;// ok + WFIFOSET(fd,7); + } } break; @@ -2839,7 +2963,9 @@ int parse_frommap(int fd) char_data = search_character(RFIFOL(fd,2), RFIFOL(fd,14)); - if (map_fd >= 0 && session[map_fd] && char_data) + if( runflag == CHARSERVER_ST_RUNNING && + session_isActive(map_fd) && + char_data ) { //Send the map server the auth of this player. struct auth_node* node; @@ -3140,7 +3266,9 @@ int parse_frommap(int fd) node = (struct auth_node*)idb_get(auth_db, account_id); cd = search_character(account_id, char_id); - if( node != NULL && cd != NULL && + if( runflag == CHARSERVER_ST_RUNNING && + cd != NULL && + node != NULL && node->account_id == account_id && node->char_id == char_id && node->login_id1 == login_id1 && @@ -3204,13 +3332,27 @@ int parse_frommap(int fd) return 0; } +void do_init_mapif(void) +{ + int i; + for( i = 0; i < ARRAYLENGTH(server); ++i ) + mapif_server_init(i); +} + +void do_final_mapif(void) +{ + int i; + for( i = 0; i < ARRAYLENGTH(server); ++i ) + mapif_server_destroy(i); +} + // Searches for the mapserver that has a given map (and optionally ip/port, if not -1). // If found, returns the server's index in the 'server' array (otherwise returns -1). int search_mapserver(unsigned short map, uint32 ip, uint16 port) { int i, j; - for(i = 0; i < MAX_MAP_SERVERS; i++) + for(i = 0; i < ARRAYLENGTH(server); i++) { if (server[i].fd > 0 && (ip == (uint32)-1 || server[i].ip == ip) @@ -3526,6 +3668,15 @@ int parse_char(int fd) WFIFOL(fd,0) = account_id; WFIFOSET(fd,4); + if( runflag != CHARSERVER_ST_RUNNING ) + { + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x6c; + WFIFOB(fd,2) = 0;// rejected from server + WFIFOSET(fd,3); + break; + } + // search authentification node = (struct auth_node*)idb_get(auth_db, account_id); if( node != NULL && @@ -3602,8 +3753,8 @@ int parse_char(int fd) if (i < 0) { unsigned short j; //First check that there's actually a map server online. - ARR_FIND( 0, MAX_MAP_SERVERS, j, server[j].fd >= 0 && server[j].map[0] ); - if (j == MAX_MAP_SERVERS) { + ARR_FIND( 0, ARRAYLENGTH(server), j, server[j].fd >= 0 && server[j].map[0] ); + if (j == ARRAYLENGTH(server)) { ShowInfo("Connection Closed. No map servers available.\n"); WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x81; @@ -3927,8 +4078,12 @@ int parse_char(int fd) char* l_pass = (char*)RFIFOP(fd,26); l_user[23] = '\0'; l_pass[23] = '\0'; - ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd <= 0 ); - if (i == MAX_MAP_SERVERS || strcmp(l_user, userid) || strcmp(l_pass, passwd)) { + ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd <= 0 ); + if( runflag != CHARSERVER_ST_RUNNING || + i == ARRAYLENGTH(server) || + strcmp(l_user, userid) != 0 || + strcmp(l_pass, passwd) != 0 ) + { WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2af9; WFIFOB(fd,2) = 3; @@ -3991,7 +4146,7 @@ int mapif_sendall(unsigned char *buf, unsigned int len) int i, c; c = 0; - for(i = 0; i < MAX_MAP_SERVERS; i++) { + for(i = 0; i < ARRAYLENGTH(server); i++) { int fd; if ((fd = server[i].fd) > 0) { WFIFOHEAD(fd,len); @@ -4009,7 +4164,7 @@ int mapif_sendallwos(int sfd, unsigned char *buf, unsigned int len) int i, c; c = 0; - for(i = 0; i < MAX_MAP_SERVERS; i++) { + for(i = 0; i < ARRAYLENGTH(server); i++) { int fd; if ((fd = server[i].fd) > 0 && fd != sfd) { WFIFOHEAD(fd,len); @@ -4027,8 +4182,8 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len) int i; if (fd >= 0) { - ARR_FIND( 0, MAX_MAP_SERVERS, i, fd == server[i].fd ); - if( i < MAX_MAP_SERVERS ) + ARR_FIND( 0, ARRAYLENGTH(server), i, fd == server[i].fd ); + if( i < ARRAYLENGTH(server) ) { WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); @@ -4039,7 +4194,7 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len) return 0; } -int broadcast_user_count(int tid, unsigned int tick, int id, intptr data) +int broadcast_user_count(int tid, unsigned int tick, int id, intptr_t data) { uint8 buf[6]; int users = count_users(); @@ -4085,7 +4240,7 @@ static int send_accounts_tologin_sub(DBKey key, void* data, va_list ap) return 0; } -int send_accounts_tologin(int tid, unsigned int tick, int id, intptr data) +int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data) { if (login_fd > 0 && session[login_fd]) { @@ -4103,7 +4258,7 @@ int send_accounts_tologin(int tid, unsigned int tick, int id, intptr data) return 0; } -int check_connect_login_server(int tid, unsigned int tick, int id, intptr data) +int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data) { if (login_fd > 0 && session[login_fd] != NULL) return 0; @@ -4136,7 +4291,7 @@ int check_connect_login_server(int tid, unsigned int tick, int id, intptr data) } // sends a ping packet to login server (will receive pong 0x2718) -int ping_login_server(int tid, unsigned int tick, int id, intptr data) +int ping_login_server(int tid, unsigned int tick, int id, intptr_t data) { if (login_fd > 0 && session[login_fd] != NULL) { @@ -4151,7 +4306,7 @@ int ping_login_server(int tid, unsigned int tick, int id, intptr data) //Invoked 15 seconds after mapif_disconnectplayer in case the map server doesn't //replies/disconnect the player we tried to kick. [Skotlex] //------------------------------------------------ -static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr data) +static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data) { struct online_char_data* character; if ((character = (struct online_char_data*)idb_get(online_char_db, id)) != NULL && character->waiting_disconnect == tid) @@ -4175,7 +4330,7 @@ static int online_data_cleanup_sub(DBKey key, void *data, va_list ap) return 0; } -static int online_data_cleanup(int tid, unsigned int tick, int id, intptr data) +static int online_data_cleanup(int tid, unsigned int tick, int id, intptr_t data) { online_char_db->foreach(online_char_db, online_data_cleanup_sub); return 0; @@ -4431,12 +4586,16 @@ int char_config_read(const char *cfgName) #ifndef TXT_SQL_CONVERT void do_final(void) { - ShowStatus("Terminating server.\n"); + ShowStatus("Terminating...\n"); mmo_char_sync(); inter_save(); set_all_offline(-1); flush_fifos(); + + do_final_mapif(); + do_final_loginif(); + // write online players files with no player online_char_db->clear(online_char_db, NULL); create_online_files(); @@ -4445,11 +4604,12 @@ void do_final(void) auth_db->destroy(auth_db, NULL); if(char_dat) aFree(char_dat); - - if (login_fd > 0) - do_close(login_fd); - if (char_fd > 0) + + if( char_fd != -1 ) + { do_close(char_fd); + char_fd = -1; + } #ifdef ENABLE_SC_SAVING status_final(); @@ -4458,6 +4618,7 @@ void do_final(void) mapindex_final(); char_log("----End of char-server (normal end with closing of all files).\n"); + ShowStatus("Finished.\n"); } //------------------------------ @@ -4473,15 +4634,27 @@ void set_server_type(void) SERVER_TYPE = ATHENA_SERVER_CHAR; } -int do_init(int argc, char **argv) -{ - int i; - for(i = 0; i < MAX_MAP_SERVERS; i++) { - memset(&server[i], 0, sizeof(struct mmo_map_server)); - server[i].fd = -1; +/// Called when a terminate signal is received. +void do_shutdown(void) +{ + if( runflag != CHARSERVER_ST_SHUTDOWN ) + { + int id; + runflag = CHARSERVER_ST_SHUTDOWN; + ShowStatus("Shutting down...\n"); + // TODO proper shutdown procedure; wait for acks?, kick all characters, ... [FlavoJS] + for( id = 0; id < ARRAYLENGTH(server); ++id ) + mapif_server_reset(id); + loginif_check_shutdown(); + flush_fifos(); + runflag = CORE_ST_STOP; } +} + +int do_init(int argc, char **argv) +{ //Read map indexes mapindex_init(); start_point.map = mapindex_name2id("new_zone01"); @@ -4512,8 +4685,6 @@ int do_init(int argc, char **argv) inter_init_txt((argc > 2) ? argv[2] : inter_cfgName); // inter server 初期化 ShowInfo("char server initialized.\n"); - set_defaultparse(parse_char); - if ((naddr_ != 0) && (!login_ip || !char_ip)) { char ip_str[16]; @@ -4533,22 +4704,13 @@ int do_init(int argc, char **argv) } } - // establish char-login connection if not present - add_timer_func_list(check_connect_login_server, "check_connect_login_server"); - add_timer_interval(gettick() + 1000, check_connect_login_server, 0, 0, 10 * 1000); - - // keep the char-login connection alive - add_timer_func_list(ping_login_server, "ping_login_server"); - add_timer_interval(gettick() + 1000, ping_login_server, 0, 0, ((int)stall_time-2) * 1000); + do_init_loginif(); + do_init_mapif(); // periodically update the overall user count on all mapservers + login server add_timer_func_list(broadcast_user_count, "broadcast_user_count"); add_timer_interval(gettick() + 1000, broadcast_user_count, 0, 0, 5 * 1000); - // send a list of all online account IDs to login server - add_timer_func_list(send_accounts_tologin, "send_accounts_tologin"); - add_timer_interval(gettick() + 1000, send_accounts_tologin, 0, 0, 3600 * 1000); //Sync online accounts every hour - // ??? add_timer_func_list(chardb_waiting_disconnect, "chardb_waiting_disconnect"); @@ -4564,10 +4726,17 @@ int do_init(int argc, char **argv) { //##TODO invoke a CONSOLE_START plugin event } - + + set_defaultparse(parse_char); char_fd = make_listen_bind(bind_ip, char_port); char_log("The char-server is ready (Server is listening on the port %d).\n", char_port); ShowStatus("The char-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %d).\n\n", char_port); + + if( runflag != CORE_ST_STOP ) + { + shutdown_callback = do_shutdown; + runflag = CHARSERVER_ST_RUNNING; + } return 0; } diff --git a/src/char/char.h b/src/char/char.h index 18bb7b1b5..bb1a530f0 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -4,8 +4,18 @@ #ifndef _CHAR_H_ #define _CHAR_H_ +#include "../common/core.h" // CORE_ST_LAST #include "../common/mmo.h" +#ifndef TXT_SQL_CONVERT +enum E_CHARSERVER_ST +{ + CHARSERVER_ST_RUNNING = CORE_ST_LAST, + CHARSERVER_ST_SHUTDOWN, + CHARSERVER_ST_LAST +}; +#endif + #define MAX_MAP_SERVERS 30 #define DEFAULT_AUTOSAVE_INTERVAL 300*1000 diff --git a/src/char/int_homun.c b/src/char/int_homun.c index d547b60f7..ec22499d0 100644 --- a/src/char/int_homun.c +++ b/src/char/int_homun.c @@ -36,7 +36,7 @@ int inter_homun_tostr(char *str,struct s_homunculus *p) for (i = 0; i < MAX_HOMUNSKILL; i++) { - if (p->hskill[i].id && !p->hskill[i].flag) + if (p->hskill[i].id && p->hskill[i].flag == SKILL_FLAG_PERMANENT) str+=sprintf(str,"%d,%d,", p->hskill[i].id, p->hskill[i].lv); } diff --git a/src/char_sql/CMakeLists.txt b/src/char_sql/CMakeLists.txt new file mode 100644 index 000000000..f2d1cd0f0 --- /dev/null +++ b/src/char_sql/CMakeLists.txt @@ -0,0 +1,57 @@ + +# +# char sql +# +if( HAVE_common_sql ) +message( STATUS "Creating target char-server_sql" ) +set( SQL_CHAR_HEADERS + "${CMAKE_CURRENT_SOURCE_DIR}/char.h" + "${CMAKE_CURRENT_SOURCE_DIR}/int_auction.h" + "${CMAKE_CURRENT_SOURCE_DIR}/int_guild.h" + "${CMAKE_CURRENT_SOURCE_DIR}/int_homun.h" + "${CMAKE_CURRENT_SOURCE_DIR}/int_mail.h" + "${CMAKE_CURRENT_SOURCE_DIR}/int_mercenary.h" + "${CMAKE_CURRENT_SOURCE_DIR}/int_party.h" + "${CMAKE_CURRENT_SOURCE_DIR}/int_pet.h" + "${CMAKE_CURRENT_SOURCE_DIR}/int_quest.h" + "${CMAKE_CURRENT_SOURCE_DIR}/int_storage.h" + "${CMAKE_CURRENT_SOURCE_DIR}/inter.h" + ) +set( SQL_CHAR_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/char.c" + "${CMAKE_CURRENT_SOURCE_DIR}/int_auction.c" + "${CMAKE_CURRENT_SOURCE_DIR}/int_guild.c" + "${CMAKE_CURRENT_SOURCE_DIR}/int_homun.c" + "${CMAKE_CURRENT_SOURCE_DIR}/int_mail.c" + "${CMAKE_CURRENT_SOURCE_DIR}/int_mercenary.c" + "${CMAKE_CURRENT_SOURCE_DIR}/int_party.c" + "${CMAKE_CURRENT_SOURCE_DIR}/int_pet.c" + "${CMAKE_CURRENT_SOURCE_DIR}/int_quest.c" + "${CMAKE_CURRENT_SOURCE_DIR}/int_storage.c" + "${CMAKE_CURRENT_SOURCE_DIR}/inter.c" + ) +set( DEPENDENCIES common_sql ) +set( LIBRARIES ${GLOBAL_LIBRARIES} ) +set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ) +set( DEFINITIONS ${GLOBAL_DEFINITIONS} ) +set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ${SQL_CHAR_HEADERS} ${SQL_CHAR_SOURCES} ) +source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ) +source_group( char FILES ${SQL_CHAR_HEADERS} ${SQL_CHAR_SOURCES} ) +include_directories( ${INCLUDE_DIRS} ) +add_executable( char-server_sql ${SOURCE_FILES} ) +add_dependencies( char-server_sql ${DEPENDENCIES} ) +target_link_libraries( char-server_sql ${LIBRARIES} ${DEPENDENCIES} ) +set_target_properties( char-server_sql PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" ) +if( WITH_COMPONENT_RUNTIME ) + cpack_add_component( Runtime_charserver_sql DESCRIPTION "char-server (sql version)" DISPLAY_NAME "char-server_sql" GROUP Runtime ) + install( TARGETS char-server_sql + DESTINATION "." + COMPONENT Runtime_charserver_sql ) +endif() +message( STATUS "Creating target char-server_sql - done" ) +set( HAVE_char-server_sql ON CACHE BOOL "char-server_sql target is available" ) +mark_as_advanced( HAVE_char-server_sql ) +else() +message( STATUS "Skipping target char-server_sql (requires common_sql)" ) +unset( HAVE_char-server_sql CACHE ) +endif() diff --git a/src/char_sql/Makefile.in b/src/char_sql/Makefile.in index 82c0a7c3f..a8cf8e08c 100644 --- a/src/char_sql/Makefile.in +++ b/src/char_sql/Makefile.in @@ -3,12 +3,16 @@ COMMON_OBJ = ../common/obj_all/core.o ../common/obj_all/socket.o ../common/obj_a ../common/obj_all/db.o ../common/obj_all/plugins.o ../common/obj_all/lock.o \ ../common/obj_all/malloc.o ../common/obj_all/showmsg.o ../common/obj_all/utils.o \ ../common/obj_all/strlib.o ../common/obj_all/grfio.o \ - ../common/obj_all/mapindex.o ../common/obj_all/ers.o + ../common/obj_all/mapindex.o ../common/obj_all/ers.o ../common/obj_all/random.o COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \ ../common/version.h ../common/db.h ../common/plugins.h ../common/lock.h \ ../common/malloc.h ../common/showmsg.h ../common/utils.h \ ../common/strlib.h ../common/grfio.h \ - ../common/mapindex.h ../common/ers.h + ../common/mapindex.h ../common/ers.h ../common/random.h + +MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o +MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h +MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar COMMON_SQL_OBJ = ../common/obj_sql/sql.o COMMON_H = ../common/sql.h @@ -19,7 +23,7 @@ CHAR_H = char.h inter.h int_party.h int_guild.h int_storage.h int_pet.h int_homu HAVE_MYSQL=@HAVE_MYSQL@ ifeq ($(HAVE_MYSQL),yes) - CHAR_SERVER_SQL_DEPENDS=obj_sql $(CHAR_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) + CHAR_SERVER_SQL_DEPENDS=obj_sql $(CHAR_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) $(MT19937AR_OBJ) else CHAR_SERVER_SQL_DEPENDS=needs_mysql endif @@ -32,7 +36,7 @@ endif all: char-server_sql char-server_sql: $(CHAR_SERVER_SQL_DEPENDS) - @CC@ @LDFLAGS@ -o ../../char-server_sql@EXEEXT@ $(CHAR_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) @LIBS@ @MYSQL_LIBS@ + @CC@ @LDFLAGS@ -o ../../char-server_sql@EXEEXT@ $(CHAR_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) $(MT19937AR_OBJ) @LIBS@ @MYSQL_LIBS@ clean: rm -rf *.o obj_sql ../../char-server_sql@EXEEXT@ @@ -53,12 +57,15 @@ needs_mysql: obj_sql: -mkdir obj_sql -obj_sql/%.o: %.c $(CHAR_H) $(COMMON_H) $(COMMON_SQL_H) - @CC@ @CFLAGS@ @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_sql/%.o: %.c $(CHAR_H) $(COMMON_H) $(COMMON_SQL_H) $(MT19937AR_H) + @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< -# missing common object files +# missing object files ../common/obj_all/%.o: @$(MAKE) -C ../common sql ../common/obj_sql/%.o: @$(MAKE) -C ../common sql + +MT19937AR_OBJ: + @$(MAKE) -C ../../3rdparty/mt19937ar diff --git a/src/char_sql/char.c b/src/char_sql/char.c index 5ad5a273b..b1c171ebf 100644 --- a/src/char_sql/char.c +++ b/src/char_sql/char.c @@ -194,7 +194,7 @@ struct online_char_data { }; static DBMap* online_char_db; // int account_id -> struct online_char_data* -static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr data); +static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data); static void* create_online_char_data(DBKey key, va_list args) { @@ -590,11 +590,11 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) //insert here. for( i = 0, count = 0; i < MAX_SKILL; ++i ) { - if(p->skill[i].id && p->skill[i].flag!=1) + if(p->skill[i].id != 0 && p->skill[i].flag != SKILL_FLAG_TEMPORARY) { if( count ) StringBuf_AppendStr(&buf, ","); - StringBuf_Printf(&buf, "('%d','%d','%d')", char_id, p->skill[i].id, (p->skill[i].flag == 0 ? p->skill[i].lv : p->skill[i].flag - 2)); + StringBuf_Printf(&buf, "('%d','%d','%d')", char_id, p->skill[i].id, (p->skill[i].flag == SKILL_FLAG_PERMANENT ? p->skill[i].lv : p->skill[i].flag - SKILL_FLAG_REPLACED_LV_0)); ++count; } } @@ -1107,7 +1107,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_USHORT, &tmp_skill.id, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_USHORT, &tmp_skill.lv, 0, NULL, NULL) ) SqlStmt_ShowDebug(stmt); - tmp_skill.flag = 0; + tmp_skill.flag = SKILL_FLAG_PERMANENT; for( i = 0; i < MAX_SKILL && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) { @@ -1543,7 +1543,7 @@ int count_users(void) int i, users; users = 0; - for(i = 0; i < MAX_MAP_SERVERS; i++) { + for(i = 0; i < ARRAYLENGTH(server); i++) { if (server[i].fd > 0) { users += server[i].users; } @@ -1778,24 +1778,75 @@ static void char_auth_ok(int fd, struct char_session_data *sd) // continues when account data is received... } -int send_accounts_tologin(int tid, unsigned int tick, int id, intptr data); +int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data); +void mapif_server_reset(int id); -int parse_fromlogin(int fd) + +/// Resets all the data. +void loginif_reset(void) +{ + int id; + // TODO kick everyone out and reset everything or wait for connect and try to reaquire locks [FlavioJS] + for( id = 0; id < ARRAYLENGTH(server); ++id ) + mapif_server_reset(id); + flush_fifos(); + exit(EXIT_FAILURE); +} + + +/// Checks the conditions for the server to stop. +/// Releases the cookie when all characters are saved. +/// If all the conditions are met, it stops the core loop. +void loginif_check_shutdown(void) +{ + if( runflag != CHARSERVER_ST_SHUTDOWN ) + return; + runflag = CORE_ST_STOP; +} + + +/// Called when the connection to Login Server is disconnected. +void loginif_on_disconnect(void) +{ + ShowWarning("Connection to Login Server lost.\n\n"); +} + + +/// Called when all the connection steps are completed. +void loginif_on_ready(void) { int i; - struct char_session_data *sd; - // only login-server can have an access to here. - // so, if it isn't the login-server, we disconnect the session. + loginif_check_shutdown(); + + //Send online accounts to login server. + send_accounts_tologin(INVALID_TIMER, gettick(), 0, 0); + + // if no map-server already connected, display a message... + ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd > 0 && server[i].map[0] ); + if( i == ARRAYLENGTH(server) ) + ShowStatus("Awaiting maps from map-server.\n"); +} + + +int parse_fromlogin(int fd) +{ + struct char_session_data* sd = NULL; + int i; + + // only process data from the login-server if( fd != login_fd ) - set_eof(fd); + { + ShowDebug("parse_fromlogin: Disconnecting invalid session #%d (is not the login-server)\n", fd); + do_close(fd); + return 0; + } - if(session[fd]->flag.eof) { - if (fd == login_fd) { - ShowWarning("Connection to login-server lost (connection #%d).\n", fd); - login_fd = -1; - } + if( session[fd]->flag.eof ) + { do_close(fd); + login_fd = -1; + loginif_on_disconnect(); return 0; } @@ -1819,16 +1870,11 @@ int parse_fromlogin(int fd) ShowError("The server communication passwords (default s1/p1) are probably invalid.\n"); ShowError("Also, please make sure your login db has the correct communication username/passwords and the gender of the account is S.\n"); ShowError("The communication passwords are set in map_athena.conf and char_athena.conf\n"); + set_eof(fd); + return 0; } else { ShowStatus("Connected to login-server (connection #%d).\n", fd); - - //Send online accounts to login server. - send_accounts_tologin(INVALID_TIMER, gettick(), 0, 0); - - // if no map-server already connected, display a message... - ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd > 0 && server[i].map[0] ); - if( i == MAX_MAP_SERVERS ) - ShowStatus("Awaiting maps from map-server.\n"); + loginif_on_ready(); } RFIFOSKIP(fd,3); break; @@ -2096,6 +2142,34 @@ int parse_fromlogin(int fd) return 0; } +int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data); +int ping_login_server(int tid, unsigned int tick, int id, intptr_t data); +int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data); + +void do_init_loginif(void) +{ + // establish char-login connection if not present + add_timer_func_list(check_connect_login_server, "check_connect_login_server"); + add_timer_interval(gettick() + 1000, check_connect_login_server, 0, 0, 10 * 1000); + + // keep the char-login connection alive + add_timer_func_list(ping_login_server, "ping_login_server"); + add_timer_interval(gettick() + 1000, ping_login_server, 0, 0, ((int)stall_time-2) * 1000); + + // send a list of all online account IDs to login server + add_timer_func_list(send_accounts_tologin, "send_accounts_tologin"); + add_timer_interval(gettick() + 1000, send_accounts_tologin, 0, 0, 3600 * 1000); //Sync online accounts every hour +} + +void do_final_loginif(void) +{ + if( login_fd != -1 ) + { + do_close(login_fd); + login_fd = -1; + } +} + int request_accreg2(int account_id, int char_id) { if (login_fd > 0) { @@ -2252,39 +2326,79 @@ int char_loadName(int char_id, char* name) int search_mapserver(unsigned short map, uint32 ip, uint16 port); + +/// Initializes a server structure. +void mapif_server_init(int id) +{ + memset(&server[id], 0, sizeof(server[id])); + server[id].fd = -1; +} + + +/// Destroys a server structure. +void mapif_server_destroy(int id) +{ + if( server[id].fd == -1 ) + { + do_close(server[id].fd); + server[id].fd = -1; + } +} + + +/// Resets all the data related to a server. +void mapif_server_reset(int id) +{ + int i,j; + unsigned char buf[16384]; + int fd = server[id].fd; + //Notify other map servers that this one is gone. [Skotlex] + WBUFW(buf,0) = 0x2b20; + WBUFL(buf,4) = htonl(server[id].ip); + WBUFW(buf,8) = htons(server[id].port); + j = 0; + for(i = 0; i < MAX_MAP_PER_SERVER; i++) + if (server[id].map[i]) + WBUFW(buf,10+(j++)*4) = server[id].map[i]; + if (j > 0) { + WBUFW(buf,2) = j * 4 + 10; + mapif_sendallwos(fd, buf, WBUFW(buf,2)); + } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ragsrvinfo` WHERE `index`='%d'", server[id].fd) ) + Sql_ShowDebug(sql_handle); + online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server. + mapif_server_destroy(id); + mapif_server_init(id); +} + + +/// Called when the connection to a Map Server is disconnected. +void mapif_on_disconnect(int id) +{ + ShowStatus("Map-server #%d has disconnected.\n", id); + mapif_server_reset(id); +} + + int parse_frommap(int fd) { int i, j; int id; - ARR_FIND( 0, MAX_MAP_SERVERS, id, server[id].fd == fd ); - if(id == MAX_MAP_SERVERS) - set_eof(fd); - if(session[fd]->flag.eof) { - if (id < MAX_MAP_SERVERS) { - unsigned char buf[16384]; - ShowStatus("Map-server %d (session #%d) has disconnected.\n", id, fd); - //Notify other map servers that this one is gone. [Skotlex] - WBUFW(buf,0) = 0x2b20; - WBUFL(buf,4) = htonl(server[id].ip); - WBUFW(buf,8) = htons(server[id].port); - j = 0; - for(i = 0; i < MAX_MAP_PER_SERVER; i++) - if (server[id].map[i]) - WBUFW(buf,10+(j++)*4) = server[id].map[i]; - if (j > 0) { - WBUFW(buf,2) = j * 4 + 10; - mapif_sendallwos(fd, buf, WBUFW(buf,2)); - } - memset(&server[id], 0, sizeof(struct mmo_map_server)); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ragsrvinfo` WHERE `index`='%d'", server[id].fd) ) - Sql_ShowDebug(sql_handle); - server[id].fd = -1; - online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server. - } + ARR_FIND( 0, ARRAYLENGTH(server), id, server[id].fd == fd ); + if( id == ARRAYLENGTH(server) ) + {// not a map server + ShowDebug("parse_frommap: Disconnecting invalid session #%d (is not a map-server)\n", fd); do_close(fd); return 0; } + if( session[fd]->flag.eof ) + { + do_close(fd); + server[id].fd = -1; + mapif_on_disconnect(id); + return 0; + } while(RFIFOREST(fd) >= 2) { @@ -2330,14 +2444,14 @@ int parse_frommap(int fd) mapif_sendallwos(fd, buf, WBUFW(buf,2)); } // Transmitting the maps of the other map-servers to the new map-server - for(x = 0; x < MAX_MAP_SERVERS; x++) { + for(x = 0; x < ARRAYLENGTH(server); x++) { if (server[x].fd > 0 && x != id) { - WFIFOHEAD(fd,10 +4*MAX_MAP_PER_SERVER); + WFIFOHEAD(fd,10 +4*ARRAYLENGTH(server)); WFIFOW(fd,0) = 0x2b04; WFIFOL(fd,4) = htonl(server[x].ip); WFIFOW(fd,8) = htons(server[x].port); j = 0; - for(i = 0; i < MAX_MAP_PER_SERVER; i++) + for(i = 0; i < ARRAYLENGTH(server); i++) if (server[x].map[i]) WFIFOW(fd,10+(j++)*4) = server[x].map[i]; if (j > 0) { @@ -2491,27 +2605,38 @@ int parse_frommap(int fd) uint32 login_id2 = RFIFOL(fd,10); uint32 ip = RFIFOL(fd,14); RFIFOSKIP(fd,18); - - // create temporary auth entry - CREATE(node, struct auth_node, 1); - node->account_id = account_id; - node->char_id = 0; - node->login_id1 = login_id1; - node->login_id2 = login_id2; - //node->sex = 0; - node->ip = ntohl(ip); - //node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server) - //node->gmlevel = 0; - idb_put(auth_db, account_id, node); - - //Set char to "@ char select" in online db [Kevin] - set_char_charselect(account_id); - - WFIFOHEAD(fd,7); - WFIFOW(fd,0) = 0x2b03; - WFIFOL(fd,2) = account_id; - WFIFOB(fd,6) = 0; - WFIFOSET(fd,7); + + if( runflag != CHARSERVER_ST_RUNNING ) + { + WFIFOHEAD(fd,7); + WFIFOW(fd,0) = 0x2b03; + WFIFOL(fd,2) = account_id; + WFIFOB(fd,6) = 0;// not ok + WFIFOSET(fd,7); + } + else + { + // create temporary auth entry + CREATE(node, struct auth_node, 1); + node->account_id = account_id; + node->char_id = 0; + node->login_id1 = login_id1; + node->login_id2 = login_id2; + //node->sex = 0; + node->ip = ntohl(ip); + //node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server) + //node->gmlevel = 0; + idb_put(auth_db, account_id, node); + + //Set char to "@ char select" in online db [Kevin] + set_char_charselect(account_id); + + WFIFOHEAD(fd,7); + WFIFOW(fd,0) = 0x2b03; + WFIFOL(fd,2) = account_id; + WFIFOB(fd,6) = 1;// ok + WFIFOSET(fd,7); + } } break; @@ -2534,8 +2659,10 @@ int parse_frommap(int fd) mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true); char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); } - - if (map_fd >= 0 && session[map_fd] && char_data) + + if( runflag == CHARSERVER_ST_RUNNING && + session_isActive(map_fd) && + char_data ) { //Send the map server the auth of this player. struct auth_node* node; @@ -2879,7 +3006,9 @@ int parse_frommap(int fd) mmo_char_fromsql(char_id, &char_dat, true); cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id); } - if( node != NULL && cd != NULL && + if( runflag == CHARSERVER_ST_RUNNING && + cd != NULL && + node != NULL && node->account_id == account_id && node->char_id == char_id && node->login_id1 == login_id1 && @@ -2942,13 +3071,27 @@ int parse_frommap(int fd) return 0; } +void do_init_mapif(void) +{ + int i; + for( i = 0; i < ARRAYLENGTH(server); ++i ) + mapif_server_init(i); +} + +void do_final_mapif(void) +{ + int i; + for( i = 0; i < ARRAYLENGTH(server); ++i ) + mapif_server_destroy(i); +} + // Searches for the mapserver that has a given map (and optionally ip/port, if not -1). // If found, returns the server's index in the 'server' array (otherwise returns -1). int search_mapserver(unsigned short map, uint32 ip, uint16 port) { int i, j; - for(i = 0; i < MAX_MAP_SERVERS; i++) + for(i = 0; i < ARRAYLENGTH(server); i++) { if (server[i].fd > 0 && (ip == (uint32)-1 || server[i].ip == ip) @@ -3276,6 +3419,15 @@ int parse_char(int fd) WFIFOL(fd,0) = account_id; WFIFOSET(fd,4); + if( runflag != CHARSERVER_ST_RUNNING ) + { + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x6c; + WFIFOB(fd,2) = 0;// rejected from server + WFIFOSET(fd,3); + break; + } + // search authentification node = (struct auth_node*)idb_get(auth_db, account_id); if( node != NULL && @@ -3361,8 +3513,8 @@ int parse_char(int fd) if (i < 0) { unsigned short j; //First check that there's actually a map server online. - ARR_FIND( 0, MAX_MAP_SERVERS, j, server[j].fd >= 0 && server[j].map[0] ); - if (j == MAX_MAP_SERVERS) { + ARR_FIND( 0, ARRAYLENGTH(server), j, server[j].fd >= 0 && server[j].map[0] ); + if (j == ARRAYLENGTH(server)) { ShowInfo("Connection Closed. No map servers available.\n"); WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x81; @@ -3665,8 +3817,12 @@ int parse_char(int fd) char* l_pass = (char*)RFIFOP(fd,26); l_user[23] = '\0'; l_pass[23] = '\0'; - ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd <= 0 ); - if (i == MAX_MAP_SERVERS || strcmp(l_user, userid) || strcmp(l_pass, passwd)) { + ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd <= 0 ); + if( runflag != CHARSERVER_ST_RUNNING || + i == ARRAYLENGTH(server) || + strcmp(l_user, userid) != 0 || + strcmp(l_pass, passwd) != 0 ) + { WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2af9; WFIFOB(fd,2) = 3; @@ -3729,7 +3885,7 @@ int mapif_sendall(unsigned char *buf, unsigned int len) int i, c; c = 0; - for(i = 0; i < MAX_MAP_SERVERS; i++) { + for(i = 0; i < ARRAYLENGTH(server); i++) { int fd; if ((fd = server[i].fd) > 0) { WFIFOHEAD(fd,len); @@ -3747,7 +3903,7 @@ int mapif_sendallwos(int sfd, unsigned char *buf, unsigned int len) int i, c; c = 0; - for(i = 0; i < MAX_MAP_SERVERS; i++) { + for(i = 0; i < ARRAYLENGTH(server); i++) { int fd; if ((fd = server[i].fd) > 0 && fd != sfd) { WFIFOHEAD(fd,len); @@ -3765,8 +3921,8 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len) int i; if (fd >= 0) { - ARR_FIND( 0, MAX_MAP_SERVERS, i, fd == server[i].fd ); - if( i < MAX_MAP_SERVERS ) + ARR_FIND( 0, ARRAYLENGTH(server), i, fd == server[i].fd ); + if( i < ARRAYLENGTH(server) ) { WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); @@ -3777,7 +3933,7 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len) return 0; } -int broadcast_user_count(int tid, unsigned int tick, int id, intptr data) +int broadcast_user_count(int tid, unsigned int tick, int id, intptr_t data) { uint8 buf[6]; int users = count_users(); @@ -3820,7 +3976,7 @@ static int send_accounts_tologin_sub(DBKey key, void* data, va_list ap) return 0; } -int send_accounts_tologin(int tid, unsigned int tick, int id, intptr data) +int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data) { if (login_fd > 0 && session[login_fd]) { @@ -3838,7 +3994,7 @@ int send_accounts_tologin(int tid, unsigned int tick, int id, intptr data) return 0; } -int check_connect_login_server(int tid, unsigned int tick, int id, intptr data) +int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data) { if (login_fd > 0 && session[login_fd] != NULL) return 0; @@ -3871,7 +4027,7 @@ int check_connect_login_server(int tid, unsigned int tick, int id, intptr data) } // sends a ping packet to login server (will receive pong 0x2718) -int ping_login_server(int tid, unsigned int tick, int id, intptr data) +int ping_login_server(int tid, unsigned int tick, int id, intptr_t data) { if (login_fd > 0 && session[login_fd] != NULL) { @@ -3886,7 +4042,7 @@ int ping_login_server(int tid, unsigned int tick, int id, intptr data) //Invoked 15 seconds after mapif_disconnectplayer in case the map server doesn't //replies/disconnect the player we tried to kick. [Skotlex] //------------------------------------------------ -static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr data) +static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data) { struct online_char_data* character; if ((character = (struct online_char_data*)idb_get(online_char_db, id)) != NULL && character->waiting_disconnect == tid) @@ -3910,7 +4066,7 @@ static int online_data_cleanup_sub(DBKey key, void *data, va_list ap) return 0; } -static int online_data_cleanup(int tid, unsigned int tick, int id, intptr data) +static int online_data_cleanup(int tid, unsigned int tick, int id, intptr_t data) { online_char_db->foreach(online_char_db, online_data_cleanup_sub); return 0; @@ -4211,7 +4367,7 @@ int char_config_read(const char* cfgName) void do_final(void) { - ShowStatus("Terminating server.\n"); + ShowStatus("Terminating...\n"); set_all_offline(-1); set_all_offline_sql(); @@ -4219,6 +4375,9 @@ void do_final(void) inter_final(); flush_fifos(); + + do_final_mapif(); + do_final_loginif(); if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ragsrvinfo`") ) Sql_ShowDebug(sql_handle); @@ -4227,13 +4386,16 @@ void do_final(void) online_char_db->destroy(online_char_db, NULL); auth_db->destroy(auth_db, NULL); - if (login_fd > 0) - do_close(login_fd); - if (char_fd > 0) + if( char_fd != -1 ) + { do_close(char_fd); + char_fd = -1; + } Sql_Free(sql_handle); mapindex_final(); + + ShowStatus("Finished.\n"); } //------------------------------ @@ -4249,15 +4411,27 @@ void set_server_type(void) SERVER_TYPE = ATHENA_SERVER_CHAR; } -int do_init(int argc, char **argv) -{ - int i; - for(i = 0; i < MAX_MAP_SERVERS; i++) { - memset(&server[i], 0, sizeof(struct mmo_map_server)); - server[i].fd = -1; +/// Called when a terminate signal is received. +void do_shutdown(void) +{ + if( runflag != CHARSERVER_ST_SHUTDOWN ) + { + int id; + runflag = CHARSERVER_ST_SHUTDOWN; + ShowStatus("Shutting down...\n"); + // TODO proper shutdown procedure; wait for acks?, kick all characters, ... [FlavoJS] + for( id = 0; id < ARRAYLENGTH(server); ++id ) + mapif_server_reset(id); + loginif_check_shutdown(); + flush_fifos(); + runflag = CORE_ST_STOP; } +} + +int do_init(int argc, char **argv) +{ //Read map indexes mapindex_init(); start_point.map = mapindex_name2id("new_zone01"); @@ -4284,8 +4458,6 @@ int do_init(int argc, char **argv) char_read_fame_list(); //Read fame lists. ShowInfo("char server initialized.\n"); - set_defaultparse(parse_char); - if ((naddr_ != 0) && (!login_ip || !char_ip)) { char ip_str[16]; @@ -4305,22 +4477,13 @@ int do_init(int argc, char **argv) } } - // establish char-login connection if not present - add_timer_func_list(check_connect_login_server, "check_connect_login_server"); - add_timer_interval(gettick() + 1000, check_connect_login_server, 0, 0, 10 * 1000); - - // keep the char-login connection alive - add_timer_func_list(ping_login_server, "ping_login_server"); - add_timer_interval(gettick() + 1000, ping_login_server, 0, 0, ((int)stall_time-2) * 1000); + do_init_loginif(); + do_init_mapif(); // periodically update the overall user count on all mapservers + login server add_timer_func_list(broadcast_user_count, "broadcast_user_count"); add_timer_interval(gettick() + 1000, broadcast_user_count, 0, 0, 5 * 1000); - // send a list of all online account IDs to login server - add_timer_func_list(send_accounts_tologin, "send_accounts_tologin"); - add_timer_interval(gettick() + 1000, send_accounts_tologin, 0, 0, 3600 * 1000); //Sync online accounts every hour - // ??? add_timer_func_list(chardb_waiting_disconnect, "chardb_waiting_disconnect"); @@ -4351,9 +4514,16 @@ int do_init(int argc, char **argv) ShowInfo("End of char server initilization function.\n"); + set_defaultparse(parse_char); ShowInfo("open port %d.....\n",char_port); char_fd = make_listen_bind(bind_ip, char_port); ShowStatus("The char-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %d).\n\n", char_port); + + if( runflag != CORE_ST_STOP ) + { + shutdown_callback = do_shutdown; + runflag = CHARSERVER_ST_RUNNING; + } return 0; } diff --git a/src/char_sql/char.h b/src/char_sql/char.h index a40340cfb..c9ec54a16 100644 --- a/src/char_sql/char.h +++ b/src/char_sql/char.h @@ -4,6 +4,17 @@ #ifndef _CHAR_SQL_H_ #define _CHAR_SQL_H_ +#include "../common/core.h" // CORE_ST_LAST + +#ifndef TXT_SQL_CONVERT +enum E_CHARSERVER_ST +{ + CHARSERVER_ST_RUNNING = CORE_ST_LAST, + CHARSERVER_ST_SHUTDOWN, + CHARSERVER_ST_LAST +}; +#endif + struct mmo_charstatus; #define MAX_MAP_SERVERS 30 diff --git a/src/char_sql/int_auction.c b/src/char_sql/int_auction.c index bba693256..04e321062 100644 --- a/src/char_sql/int_auction.c +++ b/src/char_sql/int_auction.c @@ -21,7 +21,7 @@ static DBMap* auction_db_ = NULL; // int auction_id -> struct auction_data* void auction_delete(struct auction_data *auction); -static int auction_end_timer(int tid, unsigned int tick, int id, intptr data); +static int auction_end_timer(int tid, unsigned int tick, int id, intptr_t data); static int auction_count(int char_id, bool buy) { @@ -136,7 +136,7 @@ static void mapif_Auction_message(int char_id, unsigned char result) mapif_sendall(buf,7); } -static int auction_end_timer(int tid, unsigned int tick, int id, intptr data) +static int auction_end_timer(int tid, unsigned int tick, int id, intptr_t data) { struct auction_data *auction; if( (auction = (struct auction_data *)idb_get(auction_db_, id)) != NULL ) diff --git a/src/char_sql/int_guild.c b/src/char_sql/int_guild.c index 0b3d77f07..9b5692689 100644 --- a/src/char_sql/int_guild.c +++ b/src/char_sql/int_guild.c @@ -47,7 +47,7 @@ int mapif_guild_info(int fd,struct guild *g); int guild_break_sub(int key,void *data,va_list ap); int inter_guild_tosql(struct guild *g,int flag); -static int guild_save_timer(int tid, unsigned int tick, int id, intptr data) +static int guild_save_timer(int tid, unsigned int tick, int id, intptr_t data) { static int last_id = 0; //To know in which guild we were. int state = 0; //0: Have not reached last guild. 1: Reached last guild, ready for save. 2: Some guild saved, don't do further saving. diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt new file mode 100644 index 000000000..21feb53f9 --- /dev/null +++ b/src/common/CMakeLists.txt @@ -0,0 +1,144 @@ + +# +# Create svnversion.h +# +message( STATUS "Creating svnversion.h" ) +if( SVNVERSION ) + file( WRITE ${CMAKE_CURRENT_BINARY_DIR}/svnversion.h + "#ifndef SVNVERSION\n#define SVNVERSION ${SVNVERSION}\n#endif\n" ) +else() + file( WRITE ${CMAKE_CURRENT_BINARY_DIR}/svnversion.h "" ) +endif() +set( GLOBAL_INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} CACHE INTERNAL "" ) +set( SVNVERSION ${SVNVERSION} + CACHE STRING "SVN version of the source code" ) +if( WITH_COMPONENT_DEVELOPMENT ) + install( FILES ${CMAKE_CURRENT_BINARY_DIR}/svnversion.h + DESTINATION "src/common" + COMPONENT Development_base ) +endif() +message( STATUS "Creating svnversion.h - done" ) + + +##################################################################### +# setup +# +set( COMMON_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" + CACHE PATH "common source directory" ) +mark_as_advanced( COMMON_SOURCE_DIR ) + +set( COMMON_ALL_HEADERS + "${CMAKE_CURRENT_BINARY_DIR}/svnversion.h" + "${COMMON_SOURCE_DIR}/cbasetypes.h" + "${COMMON_SOURCE_DIR}/mmo.h" + "${COMMON_SOURCE_DIR}/plugin.h" + "${COMMON_SOURCE_DIR}/version.h" + ) + +set( COMMON_MINI_HEADERS + ${COMMON_ALL_HEADERS} + "${COMMON_SOURCE_DIR}/core.h" + "${COMMON_SOURCE_DIR}/malloc.h" + "${COMMON_SOURCE_DIR}/showmsg.h" + "${COMMON_SOURCE_DIR}/strlib.h" + CACHE INTERNAL "" ) +set( COMMON_MINI_SOURCES + "${COMMON_SOURCE_DIR}/core.c" + "${COMMON_SOURCE_DIR}/malloc.c" + "${COMMON_SOURCE_DIR}/showmsg.c" + "${COMMON_SOURCE_DIR}/strlib.c" + CACHE INTERNAL "" ) +set( COMMON_MINI_DEFINITIONS MINICORE CACHE INTERNAL "" ) + + +# +# common_base +# +if( WITH_ZLIB ) +message( STATUS "Creating target common_base" ) +set( COMMON_BASE_HEADERS + ${COMMON_ALL_HEADERS} + "${COMMON_SOURCE_DIR}/core.h" + "${COMMON_SOURCE_DIR}/db.h" + "${COMMON_SOURCE_DIR}/ers.h" + "${COMMON_SOURCE_DIR}/grfio.h" + "${COMMON_SOURCE_DIR}/lock.h" + "${COMMON_SOURCE_DIR}/malloc.h" + "${COMMON_SOURCE_DIR}/mapindex.h" + "${COMMON_SOURCE_DIR}/md5calc.h" + "${COMMON_SOURCE_DIR}/nullpo.h" + "${COMMON_SOURCE_DIR}/plugins.h" + "${COMMON_SOURCE_DIR}/random.h" + "${COMMON_SOURCE_DIR}/showmsg.h" + "${COMMON_SOURCE_DIR}/socket.h" + "${COMMON_SOURCE_DIR}/strlib.h" + "${COMMON_SOURCE_DIR}/timer.h" + "${COMMON_SOURCE_DIR}/utils.h" + CACHE INTERNAL "common_base headers" ) +set( COMMON_BASE_SOURCES + "${COMMON_SOURCE_DIR}/core.c" + "${COMMON_SOURCE_DIR}/db.c" + "${COMMON_SOURCE_DIR}/ers.c" + "${COMMON_SOURCE_DIR}/grfio.c" + "${COMMON_SOURCE_DIR}/lock.c" + "${COMMON_SOURCE_DIR}/malloc.c" + "${COMMON_SOURCE_DIR}/mapindex.c" + "${COMMON_SOURCE_DIR}/md5calc.c" + "${COMMON_SOURCE_DIR}/nullpo.c" + "${COMMON_SOURCE_DIR}/plugins.c" + "${COMMON_SOURCE_DIR}/random.c" + "${COMMON_SOURCE_DIR}/showmsg.c" + "${COMMON_SOURCE_DIR}/socket.c" + "${COMMON_SOURCE_DIR}/strlib.c" + "${COMMON_SOURCE_DIR}/timer.c" + "${COMMON_SOURCE_DIR}/utils.c" + CACHE INTERNAL "common_base sources" ) +set( LIBRARIES ${ZLIB_LIBRARIES} ) +set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${MT19937AR_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS} ) +set( DEFINITIONS ${GLOBAL_DEFINITIONS} ) +set( SOURCE_FILES ${MT19937AR_HEADERS} ${MT19937AR_SOURCES} ${COMMON_BASE_HEADERS} ${COMMON_BASE_SOURCES} ) +source_group( mt19937ar FILES ${MT19937AR_HEADERS} ${MT19937AR_SOURCES} ) +source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_BASE_SOURCES} ) +add_library( common_base ${SOURCE_FILES} ) +target_link_libraries( common_base ${LIBRARIES} ) +set_target_properties( common_base PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" ) +include_directories( ${INCLUDE_DIRS} ) +message( STATUS "Creating target common_base - done" ) +set( HAVE_common_base ON CACHE BOOL "common_base target is available" ) +mark_as_advanced( HAVE_common_base ) +else() +message( STATUS "Skipping target common_base (requires ZLIB)" ) +unset( HAVE_common_base CACHE ) +endif() + + +# +# common_sql +# +if( HAVE_common_base AND WITH_MYSQL ) +message( STATUS "Creating target common_sql" ) +set( COMMON_SQL_HEADERS + ${COMMON_ALL_HEADERS} + "${CMAKE_CURRENT_SOURCE_DIR}/sql.h" + CACHE INTERNAL "common_sql headers" ) +set( COMMON_SQL_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/sql.c" + CACHE INTERNAL "common_sql sources" ) +set( DEPENDENCIES common_base ) +set( LIBRARIES ${MYSQL_LIBRARIES} ) +set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${MYSQL_INCLUDE_DIRS} ) +set( DEFINITIONS ${GLOBAL_DEFINITIONS} ) +set( SOURCE_FILES ${COMMON_SQL_HEADERS} ${COMMON_SQL_SOURCES} ) +source_group( common FILES ${COMMON_SQL_HEADERS} ${COMMON_SQL_SOURCES} ) +add_library( common_sql ${SOURCE_FILES} ) +add_dependencies( common_sql ${DEPENDENCIES} ) +target_link_libraries( common_sql ${LIBRARIES} ${DEPENDENCIES} ) +set_target_properties( common_sql PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" ) +include_directories( ${INCLUDE_DIRS} ) +message( STATUS "Creating target common_sql - done" ) +set( HAVE_common_sql ON CACHE BOOL "common_sql target is available" ) +mark_as_advanced( HAVE_common_sql ) +else() +message( STATUS "Skipping target common_sql (requires common_base and MYSQL)" ) +unset( HAVE_common_sql CACHE ) +endif() diff --git a/src/common/Makefile.in b/src/common/Makefile.in index bda9e1911..37606dde2 100644 --- a/src/common/Makefile.in +++ b/src/common/Makefile.in @@ -2,15 +2,19 @@ COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o obj_all/plugins.o obj_all/lock.o \ obj_all/nullpo.o obj_all/malloc.o obj_all/showmsg.o obj_all/strlib.o obj_all/utils.o \ obj_all/grfio.o obj_all/mapindex.o obj_all/ers.o obj_all/md5calc.o \ - obj_all/minicore.o obj_all/minisocket.o obj_all/minimalloc.o + obj_all/minicore.o obj_all/minisocket.o obj_all/minimalloc.o obj_all/random.o COMMON_H = svnversion.h mmo.h plugin.h version.h \ core.h socket.h timer.h db.h plugins.h lock.h \ nullpo.h malloc.h showmsg.h strlib.h utils.h \ - grfio.h mapindex.h ers.h md5calc.h + grfio.h mapindex.h ers.h md5calc.h random.h COMMON_SQL_OBJ = obj_sql/sql.o COMMON_SQL_H = sql.h +MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o +MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h +MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar + HAVE_MYSQL=@HAVE_MYSQL@ ifeq ($(HAVE_MYSQL),yes) ALL_DEPENDS=txt sql @@ -19,6 +23,7 @@ else ALL_TARGET=txt SQL_DEPENDS=needs_mysql endif +TXT_DEPENDS=common @SET_MAKE@ @@ -27,7 +32,7 @@ endif all: $(ALL_DEPENDS) -txt: common +txt: $(TXT_DEPENDS) sql: $(SQL_DEPENDS) @@ -54,16 +59,16 @@ obj_all: obj_sql: -mkdir obj_sql -common: obj_all $(COMMON_OBJ) +common: obj_all $(COMMON_OBJ) $(MT19937AR_OBJ) common_sql: obj_sql $(COMMON_SQL_OBJ) -obj_all/%.o: %.c $(COMMON_H) - @CC@ @CFLAGS@ @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_all/%.o: %.c $(COMMON_H) $(MT19937AR_H) + @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< -obj_all/mini%.o: %.c $(COMMON_H) - @CC@ @CFLAGS@ -DMINICORE @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_all/mini%.o: %.c $(COMMON_H) $(MT19937AR_H) + @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) -DMINICORE @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< obj_sql/%.o: %.c $(COMMON_H) $(COMMON_SQL_H) @CC@ @CFLAGS@ @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< @@ -80,3 +85,7 @@ else svnversion.h: @printf "\n" > svnversion.h endif + +# missing object files +MT19937AR_OBJ: + @$(MAKE) -C ../../3rdparty/mt19937ar diff --git a/src/common/cbasetypes.h b/src/common/cbasetypes.h index aee54a4bc..e2fe17555 100644 --- a/src/common/cbasetypes.h +++ b/src/common/cbasetypes.h @@ -78,14 +78,9 @@ // NOTE: Visual C++ uses <inttypes.h> and <stdint.h> provided in /3rdparty ////////////////////////////////////////////////////////////////////////// #include <inttypes.h> - -////////////////////////////////////////////////////////////////////////// -// typedefs to compensate type size change from 32bit to 64bit -// MS implements LLP64 model, normal unix does LP64, -// only Silicon Graphics/Cray goes ILP64 so don't care (and don't support) -////////////////////////////////////////////////////////////////////////// - +#include <stdint.h> #include <limits.h> + // ILP64 isn't supported, so always 32 bits? #ifndef UINT_MAX #define UINT_MAX 0xffffffff @@ -95,49 +90,56 @@ // Integers with guaranteed _exact_ size. ////////////////////////////////////////////////////////////////////////// -#define SIZEOF_LONG 4 -#define SIZEOF_INT 4 -#define HAVE_INT_8_16_32 +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef int64_t int64; -typedef char int8; -typedef short int16; -typedef int int32; +typedef int8_t sint8; +typedef int16_t sint16; +typedef int32_t sint32; +typedef int64_t sint64; -typedef signed char sint8; -typedef signed short sint16; -typedef signed int sint32; - -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uint64_t uint64; #undef UINT8_MIN #undef UINT16_MIN #undef UINT32_MIN -#define UINT8_MIN ((uint8) 0) -#define UINT16_MIN ((uint16)0) -#define UINT32_MIN ((uint32)0) +#undef UINT64_MIN +#define UINT8_MIN ((uint8) UINT8_C(0x00)) +#define UINT16_MIN ((uint16)UINT16_C(0x0000)) +#define UINT32_MIN ((uint32)UINT32_C(0x00000000)) +#define UINT64_MIN ((uint64)UINT64_C(0x0000000000000000)) #undef UINT8_MAX #undef UINT16_MAX #undef UINT32_MAX -#define UINT8_MAX ((uint8) 0xFF) -#define UINT16_MAX ((uint16)0xFFFF) -#define UINT32_MAX ((uint32)0xFFFFFFFF) +#undef UINT64_MAX +#define UINT8_MAX ((uint8) UINT8_C(0xFF)) +#define UINT16_MAX ((uint16)UINT16_C(0xFFFF)) +#define UINT32_MAX ((uint32)UINT32_C(0xFFFFFFFF)) +#define UINT64_MAX ((uint64)UINT64_C(0xFFFFFFFFFFFFFFFF)) #undef SINT8_MIN #undef SINT16_MIN #undef SINT32_MIN -#define SINT8_MIN ((sint8) 0x80) -#define SINT16_MIN ((sint16)0x8000) -#define SINT32_MIN ((sint32)0x80000000) +#undef SINT64_MIN +#define SINT8_MIN ((sint8) INT8_C(0x80)) +#define SINT16_MIN ((sint16)INT16_C(0x8000)) +#define SINT32_MIN ((sint32)INT32_C(0x80000000)) +#define SINT64_MIN ((sint32)INT64_C(0x8000000000000000)) #undef SINT8_MAX #undef SINT16_MAX #undef SINT32_MAX -#define SINT8_MAX ((sint8) 0x7F) -#define SINT16_MAX ((sint16)0x7FFF) -#define SINT32_MAX ((sint32)0x7FFFFFFF) +#undef SINT64_MAX +#define SINT8_MAX ((sint8) INT8_C(0x7F)) +#define SINT16_MAX ((sint16)INT16_C(0x7FFF)) +#define SINT32_MAX ((sint32)INT32_C(0x7FFFFFFF)) +#define SINT64_MAX ((sint64)INT64_C(0x7FFFFFFFFFFFFFFF)) ////////////////////////////////////////////////////////////////////////// // Integers with guaranteed _minimum_ size. @@ -173,51 +175,10 @@ typedef int ssize_t; ////////////////////////////////////////////////////////////////////////// -// portable 64-bit integers -////////////////////////////////////////////////////////////////////////// -#if defined(_MSC_VER) || defined(__BORLANDC__) -typedef __int64 int64; -typedef signed __int64 sint64; -typedef unsigned __int64 uint64; -#else -typedef long long int64; -typedef signed long long sint64; -typedef unsigned long long uint64; -#endif - -#ifndef INT64_MIN -#define INT64_MIN (INT64_C(-9223372036854775807)-1) -#endif -#ifndef INT64_MAX -#define INT64_MAX (INT64_C(9223372036854775807)) -#endif -#ifndef UINT64_MAX -#define UINT64_MAX (UINT64_C(18446744073709551615)) -#endif - - -////////////////////////////////////////////////////////////////////////// // pointer sized integers ////////////////////////////////////////////////////////////////////////// -#undef UINTPTR_MIN -#undef UINTPTR_MAX -#undef INTPTR_MIN -#undef INTPTR_MAX -#ifdef __64BIT__ -typedef uint64 uintptr; -typedef int64 intptr; -#define UINTPTR_MIN UINT64_MIN -#define UINTPTR_MAX UINT64_MAX -#define INTPTR_MIN INT64_MIN -#define INTPTR_MAX INT64_MAX -#else -typedef uint32 uintptr; -typedef int32 intptr; -#define UINTPTR_MIN UINT32_MIN -#define UINTPTR_MAX UINT32_MAX -#define INTPTR_MIN INT32_MIN -#define INTPTR_MAX INT32_MAX -#endif +typedef intptr_t intptr; +typedef uintptr_t uintptr; ////////////////////////////////////////////////////////////////////////// diff --git a/src/common/core.c b/src/common/core.c index b89cc3841..bfa563d8c 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -24,7 +24,12 @@ #include <unistd.h> #endif -int runflag = 1; + +/// Called when a terminate signal is received. +void (*shutdown_callback)(void) = NULL; + + +int runflag = CORE_ST_RUN; int arg_c = 0; char **arg_v = NULL; @@ -78,7 +83,10 @@ static void sig_proc(int sn) case SIGTERM: if (++is_called > 3) exit(EXIT_SUCCESS); - runflag = 0; + if( shutdown_callback != NULL ) + shutdown_callback(); + else + runflag = CORE_ST_STOP;// auto-shutdown break; case SIGSEGV: case SIGFPE: @@ -249,7 +257,7 @@ int main (int argc, char **argv) {// Main runtime cycle int next; - while (runflag) { + while (runflag != CORE_ST_STOP) { next = do_timer(gettick_nocache()); do_sockets(next); } diff --git a/src/common/core.h b/src/common/core.h index fc4af3e3e..beb72d080 100644 --- a/src/common/core.h +++ b/src/common/core.h @@ -7,6 +7,7 @@ extern int arg_c; extern char **arg_v; +/// @see E_CORE_ST extern int runflag; extern char *SERVER_NAME; extern char SERVER_TYPE; @@ -18,4 +19,16 @@ extern void set_server_type(void); extern void do_abort(void); extern void do_final(void); +/// The main loop continues until runflag is CORE_ST_STOP +enum E_CORE_ST +{ + CORE_ST_STOP = 0, + CORE_ST_RUN, + CORE_ST_LAST +}; + +/// Called when a terminate signal is received. (Ctrl+C pressed) +/// If NULL, runflag is set to CORE_ST_STOP instead. +extern void (*shutdown_callback)(void); + #endif /* _CORE_H_ */ diff --git a/src/common/db.c b/src/common/db.c index 595ed241d..c9b124455 100644 --- a/src/common/db.c +++ b/src/common/db.c @@ -67,13 +67,13 @@ \*****************************************************************************/ #include <stdio.h> #include <stdlib.h> -#include <string.h> #include "db.h" #include "../common/mmo.h" #include "../common/malloc.h" #include "../common/showmsg.h" #include "../common/ers.h" +#include "../common/strlib.h" /*****************************************************************************\ * (1) Private typedefs, enums, structures, defines and global variables of * @@ -271,6 +271,7 @@ static struct db_stats { uint32 dbit_remove; uint32 dbit_destroy; uint32 db_iterator; + uint32 db_exists; uint32 db_get; uint32 db_getall; uint32 db_vgetall; @@ -304,7 +305,7 @@ static struct db_stats { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0 }; #define DB_COUNTSTAT(token) if (stats. ## token != UINT32_MAX) ++stats. ## token #else /* !defined(DB_ENABLE_STATS) */ @@ -630,19 +631,17 @@ static int db_is_key_null(DBType type, DBKey key) static DBKey db_dup_key(DBMap_impl* db, DBKey key) { char *str; + size_t len; DB_COUNTSTAT(db_dup_key); switch (db->type) { case DB_STRING: case DB_ISTRING: - if (db->maxlen) { - CREATE(str, char, db->maxlen +1); - strncpy(str, key.str, db->maxlen); - str[db->maxlen] = '\0'; - key.str = str; - } else { - key.str = (char *)aStrdup(key.str); - } + len = strnlen(key.str, db->maxlen); + str = (char*)aMalloc(len + 1); + memcpy(str, key.str, len); + str[len] = '\0'; + key.str = str; return key; default: @@ -888,8 +887,6 @@ static int db_uint_cmp(DBKey key1, DBKey key2, unsigned short maxlen) static int db_string_cmp(DBKey key1, DBKey key2, unsigned short maxlen) { DB_COUNTSTAT(db_string_cmp); - if (maxlen == 0) - maxlen = UINT16_MAX; return strncmp((const char *)key1.str, (const char *)key2.str, maxlen); } @@ -908,8 +905,6 @@ static int db_string_cmp(DBKey key1, DBKey key2, unsigned short maxlen) static int db_istring_cmp(DBKey key1, DBKey key2, unsigned short maxlen) { DB_COUNTSTAT(db_istring_cmp); - if (maxlen == 0) - maxlen = UINT16_MAX; return strncasecmp((const char *)key1.str, (const char *)key2.str, maxlen); } @@ -951,7 +946,6 @@ static unsigned int db_uint_hash(DBKey key, unsigned short maxlen) /** * Default hasher for DB_STRING databases. - * If maxlen if 0, the maximum number of maxlen is used instead. * @param key Key to be hashed * @param maxlen Maximum length of the key to hash * @return hash of the key @@ -966,8 +960,6 @@ static unsigned int db_string_hash(DBKey key, unsigned short maxlen) unsigned short i; DB_COUNTSTAT(db_string_hash); - if (maxlen == 0) - maxlen = UINT16_MAX; for (i = 0; *k; ++i) { hash = (hash*33 + ((unsigned char)*k))^(hash>>24); @@ -981,7 +973,6 @@ static unsigned int db_string_hash(DBKey key, unsigned short maxlen) /** * Default hasher for DB_ISTRING databases. - * If maxlen if 0, the maximum number of maxlen is used instead. * @param key Key to be hashed * @param maxlen Maximum length of the key to hash * @return hash of the key @@ -995,8 +986,6 @@ static unsigned int db_istring_hash(DBKey key, unsigned short maxlen) unsigned short i; DB_COUNTSTAT(db_istring_hash); - if (maxlen == 0) - maxlen = UINT16_MAX; for (i = 0; *k; i++) { hash = (hash*33 + ((unsigned char)TOLOWER(*k)))^(hash>>24); @@ -1087,6 +1076,7 @@ static void db_release_both(DBKey key, void *data, DBRelease which) * dbit_obj_destroy - Destroys the iterator, unlocking the database and * * freeing used memory. * * db_obj_iterator - Return a new databse iterator. * + * db_obj_exists - Checks if an entry exists. * * db_obj_get - Get the data identified by the key. * * db_obj_vgetall - Get the data of the matched entries. * * db_obj_getall - Get the data of the matched entries. * @@ -1402,6 +1392,57 @@ static DBIterator* db_obj_iterator(DBMap* self) } /** + * Returns true if the entry exists. + * @param self Interface of the database + * @param key Key that identifies the entry + * @return true is the entry exists + * @protected + * @see DBMap#exists + */ +static bool db_obj_exists(DBMap* self, DBKey key) +{ + DBMap_impl* db = (DBMap_impl*)self; + DBNode node; + int c; + bool found = false; + + DB_COUNTSTAT(db_exists); + if (db == NULL) return false; // nullpo candidate + if (!(db->options&DB_OPT_ALLOW_NULL_KEY) && db_is_key_null(db->type, key)) { + return false; // nullpo candidate + } + + if (db->cache && db->cmp(key, db->cache->key, db->maxlen) == 0) { +#if defined(DEBUG) + if (db->cache->deleted) { + ShowDebug("db_exists: Cache contains a deleted node. Please report this!!!\n"); + return false; + } +#endif + return true; // cache hit + } + + db_free_lock(db); + node = db->ht[db->hash(key, db->maxlen)%HASH_SIZE]; + while (node) { + c = db->cmp(key, node->key, db->maxlen); + if (c == 0) { + if (!(node->deleted)) { + db->cache = node; + found = true; + } + break; + } + if (c < 0) + node = node->left; + else + node = node->right; + } + db_free_unlock(db); + return found; +} + +/** * Get the data of the entry identifid by the key. * @param self Interface of the database * @param key Key that identifies the entry @@ -2326,7 +2367,7 @@ DBReleaser db_custom_release(DBRelease which) * @param type Type of database * @param options Options of the database * @param maxlen Maximum length of the string to be used as key in string - * databases + * databases. If 0, the maximum number of maxlen is used (64K). * @return The interface of the database * @public * @see #DBMap_impl @@ -2351,6 +2392,7 @@ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsi options = db_fix_options(type, options); /* Interface of the database */ db->vtable.iterator = db_obj_iterator; + db->vtable.exists = db_obj_exists; db->vtable.get = db_obj_get; db->vtable.getall = db_obj_getall; db->vtable.vgetall = db_obj_vgetall; @@ -2389,6 +2431,9 @@ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsi db->maxlen = maxlen; db->global_lock = 0; + if( db->maxlen == 0 && (type == DB_STRING || type == DB_ISTRING) ) + db->maxlen = UINT16_MAX; + return &db->vtable; } @@ -2493,7 +2538,7 @@ void db_final(void) "dbit_next %10u, dbit_prev %10u,\n" "dbit_exists %10u, dbit_remove %10u,\n" "dbit_destroy %10u, db_iterator %10u,\n" - "db_get %10u,\n" + "db_exits %10u, db_get %10u,\n" "db_getall %10u, db_vgetall %10u,\n" "db_ensure %10u, db_vensure %10u,\n" "db_put %10u, db_remove %10u,\n" @@ -2523,7 +2568,7 @@ void db_final(void) stats.dbit_next, stats.dbit_prev, stats.dbit_exists, stats.dbit_remove, stats.dbit_destroy, stats.db_iterator, - stats.db_get, + stats.db_exists, stats.db_get, stats.db_getall, stats.db_vgetall, stats.db_ensure, stats.db_vensure, stats.db_put, stats.db_remove, diff --git a/src/common/db.h b/src/common/db.h index c1b224bcd..d33b8ec2e 100644 --- a/src/common/db.h +++ b/src/common/db.h @@ -205,8 +205,6 @@ typedef int (*DBMatcher)(DBKey key, void* data, va_list args); /** * Format of the comparators used internally by the database system. * Compares key1 to key2. - * <code>maxlen</code> is the maximum number of character used in DB_STRING and - * DB_ISTRING databases. If 0, the maximum number of maxlen is used (64K). * Returns 0 is equal, negative if lower and positive is higher. * @param key1 Key being compared * @param key2 Key we are comparing to @@ -221,8 +219,6 @@ typedef int (*DBComparator)(DBKey key1, DBKey key2, unsigned short maxlen); /** * Format of the hashers used internally by the database system. * Creates the hash of the key. - * <code>maxlen</code> is the maximum number of character used in DB_STRING and - * DB_ISTRING databases. If 0, the maximum number of maxlen is used (64K). * @param key Key being hashed * @param maxlen Maximum number of characters used in DB_STRING and DB_ISTRING * databases. @@ -360,6 +356,15 @@ struct DBMap { DBIterator* (*iterator)(DBMap* self); /** + * Returns true if the entry exists. + * @param self Database + * @param key Key that identifies the entry + * @return true is the entry exists + * @protected + */ + bool (*exists)(DBMap* self, DBKey key); + + /** * Get the data of the entry identifid by the key. * @param self Database * @param key Key that identifies the entry @@ -580,6 +585,11 @@ struct DBMap { # define str2key(k) ((DBKey)(const char *)(k)) #endif /* not DB_MANUAL_CAST_TO_UNION */ +#define db_exists(db,k) ( (db)->exists((db),(k)) ) +#define idb_exists(db,k) ( (db)->exists((db),i2key(k)) ) +#define uidb_exists(db,k) ( (db)->exists((db),ui2key(k)) ) +#define strdb_exists(db,k) ( (db)->exists((db),str2key(k)) ) + #define db_get(db,k) ( (db)->get((db),(k)) ) #define idb_get(db,k) ( (db)->get((db),i2key(k)) ) #define uidb_get(db,k) ( (db)->get((db),ui2key(k)) ) @@ -707,7 +717,7 @@ DBReleaser db_custom_release(DBRelease which); * @param type Type of database * @param options Options of the database * @param maxlen Maximum length of the string to be used as key in string - * databases + * databases. If 0, the maximum number of maxlen is used (64K). * @return The interface of the database * @public * @see #DBType diff --git a/src/common/ers.h b/src/common/ers.h index 47a076e6e..9e120c313 100644 --- a/src/common/ers.h +++ b/src/common/ers.h @@ -40,9 +40,7 @@ #ifndef _ERS_H_ #define _ERS_H_ -#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" -#endif /*****************************************************************************\ * (1) All public parts of the Entry Reusage System. * diff --git a/src/common/grfio.c b/src/common/grfio.c index e7549ecb4..cb242fe5d 100644 --- a/src/common/grfio.c +++ b/src/common/grfio.c @@ -1,19 +1,18 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> - -#include "grfio.h" - #include "../common/cbasetypes.h" #include "../common/showmsg.h" #include "../common/malloc.h" #include "../common/strlib.h" #include "../common/utils.h" +#include "grfio.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <zlib.h> //---------------------------- // file entry table struct @@ -221,6 +220,23 @@ unsigned long grfio_crc32 (const unsigned char* buf, unsigned int len) return crc32(crc32(0L, Z_NULL, 0), buf, len); } + +/////////////////////////////////////////////////////////////////////////////// +/// Grf data sub : zip decode +int decode_zip(unsigned char* dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen) +{ + return uncompress(dest, destLen, source, sourceLen); +} + + +/////////////////////////////////////////////////////////////////////////////// +/// Grf data sub : zip encode +int encode_zip(unsigned char* dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen) +{ + return compress(dest, destLen, source, sourceLen); +} + + /*********************************************************** *** File List Subroutines *** ***********************************************************/ @@ -431,9 +447,9 @@ void* grfio_reads(char* fname, int* size) if (entry->cycle >= 0) decode_des_etc(buf, entry->srclen_aligned, entry->cycle == 0, entry->cycle); len = entry->declen; - uncompress(buf2, &len, buf, entry->srclen); + decode_zip(buf2, &len, buf, entry->srclen); if (len != (uLong)entry->declen) { - ShowError("uncompress size mismatch err: %d != %d\n", (int)len, entry->declen); + ShowError("decode_zip size mismatch err: %d != %d\n", (int)len, entry->declen); aFree(buf); aFree(buf2); return NULL; @@ -580,7 +596,7 @@ static int grfio_entryread(char* grfname, int gentry) grf_filelist = (unsigned char *)aMallocA(eSize); // Get a Extend Size fread(rBuf,1,rSize,fp); fclose(fp); - uncompress(grf_filelist, &eSize, rBuf, rSize); // Decode function + decode_zip(grf_filelist, &eSize, rBuf, rSize); // Decode function list_size = eSize; aFree(rBuf); diff --git a/src/common/grfio.h b/src/common/grfio.h index d5334ccf3..d0baa6609 100644 --- a/src/common/grfio.h +++ b/src/common/grfio.h @@ -4,8 +4,6 @@ #ifndef _GRFIO_H_ #define _GRFIO_H_ -#include <zlib.h> - void grfio_init(char*); // GRFIO Initialize void grfio_final(void); // GRFIO Finalize void* grfio_reads(char*,int*); // GRFIO data file read & size get @@ -16,4 +14,7 @@ char *grfio_find_file(char *fname); int grfio_size(char*); // GRFIO data file size get unsigned long grfio_crc32(const unsigned char *buf, unsigned int len); +int decode_zip(unsigned char* dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen); +int encode_zip(unsigned char* dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen); + #endif /* _GRFIO_H_ */ diff --git a/src/common/malloc.c b/src/common/malloc.c index b566e689f..f80d11fb4 100644 --- a/src/common/malloc.c +++ b/src/common/malloc.c @@ -222,7 +222,7 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func ) if (((long) size) < 0) { ShowError("_mmalloc: %d\n", size); - return 0; + return NULL; } if(size == 0) { @@ -380,7 +380,7 @@ void _mfree(void *ptr, const char *file, int line, const char *func ) { ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line); } else { - head->size = -1; + head->size = 0xFFFF; if(head_large->prev) { head_large->prev->next = head_large->next; } else { @@ -428,7 +428,7 @@ void _mfree(void *ptr, const char *file, int line, const char *func ) hash_unfill[ block->unit_hash ] = block; } head->size = block->unit_unfill; - block->unit_unfill = (unsigned short)(((uintptr)head - (uintptr)block->data) / block->unit_size); + block->unit_unfill = (unsigned short)(((uintptr_t)head - (uintptr_t)block->data) / block->unit_size); } } } @@ -636,7 +636,6 @@ static void memmgr_final (void) fclose(log_fp); } #endif /* LOG_MEMMGR */ - return; } static void memmgr_init (void) @@ -646,7 +645,6 @@ static void memmgr_init (void) ShowStatus("Memory manager initialised: "CL_WHITE"%s"CL_RESET"\n", memmer_logfile); memset(hash_unfill, 0, sizeof(hash_unfill)); #endif /* LOG_MEMMGR */ - return; } #endif /* USE_MEMMGR */ @@ -679,7 +677,6 @@ void malloc_final (void) #ifdef USE_MEMMGR memmgr_final (); #endif - return; } void malloc_init (void) @@ -687,5 +684,4 @@ void malloc_init (void) #ifdef USE_MEMMGR memmgr_init (); #endif - return; } diff --git a/src/common/mmo.h b/src/common/mmo.h index 0bc30ea47..f9037e913 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -207,8 +207,19 @@ struct point { short x,y; }; +enum e_skill_flag +{ + SKILL_FLAG_PERMANENT, + SKILL_FLAG_TEMPORARY, + SKILL_FLAG_PLAGIARIZED, + SKILL_FLAG_REPLACED_LV_0, // temporary skill overshadowing permanent skill of level 'N - SKILL_FLAG_REPLACED_LV_0' + //... +}; + struct s_skill { - unsigned short id,lv,flag; + unsigned short id; + unsigned short lv; + unsigned short flag; // see enum e_skill_flag }; struct global_reg { @@ -508,12 +519,6 @@ struct guild_castle { int temp_guardians_max; }; -// for Brandish Spear calculations -struct square { - int val1[5]; - int val2[5]; -}; - struct fame_list { int id; int fame; diff --git a/src/common/plugin.h b/src/common/plugin.h index fd01be762..a367d2537 100644 --- a/src/common/plugin.h +++ b/src/common/plugin.h @@ -4,9 +4,7 @@ #ifndef _PLUGIN_H_ #define _PLUGIN_H_ -#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" -#endif ////// Plugin functions /////////////// diff --git a/src/common/plugins.h b/src/common/plugins.h index e71a4e8c5..c1cf17afd 100644 --- a/src/common/plugins.h +++ b/src/common/plugins.h @@ -4,10 +4,7 @@ #ifndef _PLUGINS_H_ #define _PLUGINS_H_ -#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" -#endif - #include "../common/plugin.h" ////// Dynamic Link Library functions /////////////// diff --git a/src/common/random.c b/src/common/random.c new file mode 100644 index 000000000..b7f2c080c --- /dev/null +++ b/src/common/random.c @@ -0,0 +1,83 @@ +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include "../common/timer.h" // gettick +#include "random.h" +#if defined(WIN32) + #define WIN32_LEAN_AND_MEAN + #include <windows.h> +#elif defined(HAVE_GETPID) || defined(HAVE_GETTID) + #include <sys/types.h> + #include <unistd.h> +#endif +#include <time.h> // time +#include <mt19937ar.h> // init_genrand, genrand_int32, genrand_res53 + + +/// Initializes the random number generator with an appropriate seed. +void rnd_init(void) +{ + uint32 seed = gettick(); + seed += (uint32)time(NULL); +#if defined(WIN32) + seed += GetCurrentProcessId(); + seed += GetCurrentThreadId(); +#else +#if defined(HAVE_GETPID) + seed += (uint32)getpid(); +#endif // HAVE_GETPID +#if defined(HAVE_GETTID) + seed += (uint32)gettid(); +#endif // HAVE_GETTID +#endif + init_genrand(seed); +} + + +/// Initializes the random number generator. +void rnd_seed(uint32 seed) +{ + init_genrand(seed); +} + + +/// Generates a random number in the interval [0, UINT32_MAX] +uint32 rnd(void) +{ + return (uint32)genrand_int32(); +} + + +/// Generates a random number in the interval [0, dice_faces) +/// NOTE: interval is open ended, so dice_faces is excluded (unless it's 0) +uint32 rnd_roll(uint32 dice_faces) +{ + return (uint32)(rnd_uniform()*dice_faces); +} + + +/// Generates a random number in the interval [min, max] +/// Returns min if range is invalid. +int32 rnd_value(int32 min, int32 max) +{ + if( min >= max ) + return min; + return min + (int32)(rnd_uniform()*(max-min+1)); +} + + +/// Generates a random number in the interval [0.0, 1.0) +/// NOTE: interval is open ended, so 1.0 is excluded +double rnd_uniform(void) +{ + return ((uint32)genrand_int32())*(1.0/4294967296.0);// divided by 2^32 +} + + +/// Generates a random number in the interval [0.0, 1.0) with 53-bit resolution +/// NOTE: interval is open ended, so 1.0 is excluded +/// NOTE: 53 bits is the maximum precision of a double +double rnd_uniform53(void) +{ + return genrand_res53(); +} diff --git a/src/common/random.h b/src/common/random.h new file mode 100644 index 000000000..59b609464 --- /dev/null +++ b/src/common/random.h @@ -0,0 +1,18 @@ +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#ifndef _RANDOM_H_ +#define _RANDOM_H_ + +#include "../common/cbasetypes.h" + +void rnd_init(void); +void rnd_seed(uint32); + +uint32 rnd(void);// [0, UINT32_MAX] +uint32 rnd_roll(uint32 dice_faces);// [0, dice_faces) +int32 rnd_value(int32 min, int32 max);// [min, max] +double rnd_uniform(void);// [0.0, 1.0) +double rnd_uniform53(void);// [0.0, 1.0) + +#endif /* _RANDOM_H_ */ diff --git a/src/common/socket.c b/src/common/socket.c index 262351dcf..81ea19468 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -938,7 +938,7 @@ static int connect_check_(uint32 ip) /// Timer function. /// Deletes old connection history records. -static int connect_check_clear(int tid, unsigned int tick, int id, intptr data) +static int connect_check_clear(int tid, unsigned int tick, int id, intptr_t data) { int i; int clear = 0; @@ -1118,6 +1118,9 @@ void socket_final(void) /// Closes a socket. void do_close(int fd) { + if( fd <= 0 ||fd >= FD_SETSIZE ) + return;// invalid + flush_fifo(fd); // Try to send what's left (although it might not succeed since it's a nonblocking socket) sFD_CLR(fd, &readfds);// this needs to be done before closing the socket sShutdown(fd, SHUT_RDWR); // Disallow further reads/writes diff --git a/src/common/socket.h b/src/common/socket.h index 2f0ec6081..a5d519d0e 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -4,9 +4,7 @@ #ifndef _SOCKET_H_ #define _SOCKET_H_ -#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" -#endif #ifdef WIN32 #define WIN32_LEAN_AND_MEAN // otherwise winsock2.h includes full windows.h diff --git a/src/common/sql.c b/src/common/sql.c index d8e397e8d..edac5a297 100644 --- a/src/common/sql.c +++ b/src/common/sql.c @@ -182,7 +182,7 @@ int Sql_Ping(Sql* self) /// Wrapper function for Sql_Ping. /// /// @private -static int Sql_P_KeepaliveTimer(int tid, unsigned int tick, int id, intptr data) +static int Sql_P_KeepaliveTimer(int tid, unsigned int tick, int id, intptr_t data) { Sql* self = (Sql*)data; ShowInfo("Pinging SQL server to keep connection alive...\n"); @@ -212,7 +212,7 @@ static int Sql_P_Keepalive(Sql* self) // establish keepalive ping_interval = timeout - 30; // 30-second reserve //add_timer_func_list(Sql_P_KeepaliveTimer, "Sql_P_KeepaliveTimer"); - return add_timer_interval(gettick() + ping_interval*1000, Sql_P_KeepaliveTimer, 0, (intptr)self, ping_interval*1000); + return add_timer_interval(gettick() + ping_interval*1000, Sql_P_KeepaliveTimer, 0, (intptr_t)self, ping_interval*1000); } diff --git a/src/common/sql.h b/src/common/sql.h index ef76b2ec5..5b318ab4d 100644 --- a/src/common/sql.h +++ b/src/common/sql.h @@ -4,9 +4,7 @@ #ifndef _COMMON_SQL_H_ #define _COMMON_SQL_H_ -#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" -#endif #include <stdarg.h>// va_list diff --git a/src/common/strlib.c b/src/common/strlib.c index 66f281ffc..097f499e6 100644 --- a/src/common/strlib.c +++ b/src/common/strlib.c @@ -441,30 +441,13 @@ bool bin2hex(char* output, unsigned char* input, size_t count) ///////////////////////////////////////////////////////////////////// -/// Parses a delim-separated string. -/// Starts parsing at startoff and fills the pos array with position pairs. -/// out_pos[0] and out_pos[1] are the start and end of line. -/// Other position pairs are the start and end of fields. -/// Returns the number of fields found or -1 if an error occurs. -/// -/// out_pos can be NULL. -/// If a line terminator is found, the end position is placed there. -/// out_pos[2] and out_pos[3] for the first field, out_pos[4] and out_pos[5] -/// for the seconds field and so on. -/// Unfilled positions are set to -1. -/// -/// @param str String to parse -/// @param len Length of the string -/// @param startoff Where to start parsing -/// @param delim Field delimiter -/// @param out_pos Array of resulting positions -/// @param npos Size of the pos array -/// @param opt Options that determine the parsing behaviour -/// @return Number of fields found in the string or -1 if an error occured -int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, int npos, enum e_svopt opt) +/// Parses a single field in a delim-separated string. +/// The delimiter after the field is skipped. +/// +/// @param sv Parse state +/// @return 1 if a field was parsed, 0 if already done, -1 on error. +int sv_parse_next(struct s_svstate* sv) { - int i; - int count; enum { START_OF_FIELD, PARSING_FIELD, @@ -473,27 +456,37 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i TERMINATE, END } state; + const char* str; + int len; + enum e_svopt opt; + char delim; + int i; - // check pos/npos - if( out_pos == NULL ) npos = 0; - for( i = 0; i < npos; ++i ) - out_pos[i] = -1; + if( sv == NULL ) + return -1;// error + + str = sv->str; + len = sv->len; + opt = sv->opt; + delim = sv->delim; // check opt if( delim == '\n' && (opt&(SV_TERMINATE_CRLF|SV_TERMINATE_LF)) ) { - ShowError("sv_parse: delimiter '\\n' is not compatible with options SV_TERMINATE_LF or SV_TERMINATE_CRLF.\n"); + ShowError("sv_parse_next: delimiter '\\n' is not compatible with options SV_TERMINATE_LF or SV_TERMINATE_CRLF.\n"); return -1;// error } if( delim == '\r' && (opt&(SV_TERMINATE_CRLF|SV_TERMINATE_CR)) ) { - ShowError("sv_parse: delimiter '\\r' is not compatible with options SV_TERMINATE_CR or SV_TERMINATE_CRLF.\n"); + ShowError("sv_parse_next: delimiter '\\r' is not compatible with options SV_TERMINATE_CR or SV_TERMINATE_CRLF.\n"); return -1;// error } - // check str - if( str == NULL ) + if( sv->done || str == NULL ) + { + sv->done = true; return 0;// nothing to parse + } #define IS_END() ( i >= len ) #define IS_DELIM() ( str[i] == delim ) @@ -502,16 +495,13 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i ((opt&SV_TERMINATE_CR) && str[i] == '\r') || \ ((opt&SV_TERMINATE_CRLF) && i+1 < len && str[i] == '\r' && str[i+1] == '\n') ) #define IS_C_ESCAPE() ( (opt&SV_ESCAPE_C) && str[i] == '\\' ) -#define SET_FIELD_START() if( npos > count*2+2 ) out_pos[count*2+2] = i -#define SET_FIELD_END() if( npos > count*2+3 ) out_pos[count*2+3] = i; ++count +#define SET_FIELD_START() sv->start = i +#define SET_FIELD_END() sv->end = i - i = startoff; - count = 0; + i = sv->off; state = START_OF_FIELD; - if( npos > 0 ) out_pos[0] = startoff;// start while( state != END ) { - if( npos > 1 ) out_pos[1] = i;// end switch( state ) { case START_OF_FIELD:// record start of field and start parsing it @@ -533,7 +523,7 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i ++i;// '\\' if( IS_END() ) { - ShowError("sv_parse: empty escape sequence\n"); + ShowError("sv_parse_next: empty escape sequence\n"); return -1; } if( str[i] == 'x' ) @@ -541,7 +531,7 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i ++i;// 'x' if( IS_END() || !ISXDIGIT(str[i]) ) { - ShowError("sv_parse: \\x with no following hex digits\n"); + ShowError("sv_parse_next: \\x with no following hex digits\n"); return -1; } do{ @@ -562,26 +552,22 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i } else { - ShowError("sv_parse: unknown escape sequence \\%c\n", str[i]); + ShowError("sv_parse_next: unknown escape sequence \\%c\n", str[i]); return -1; } state = PARSING_FIELD; break; } - case END_OF_FIELD:// record end of field and continue + case END_OF_FIELD:// record end of field and stop SET_FIELD_END(); + state = END; if( IS_END() ) - state = END; + ;// nothing else else if( IS_DELIM() ) - { ++i;// delim - state = START_OF_FIELD; - } else if( IS_TERMINATOR() ) state = TERMINATE; - else - state = START_OF_FIELD; break; case TERMINATE: @@ -592,10 +578,14 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i else ++i;// CR or LF #endif + sv->done = true; state = END; break; } } + if( IS_END() ) + sv->done = true; + sv->off = i; #undef IS_END #undef IS_DELIM @@ -604,6 +594,58 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i #undef SET_FIELD_START #undef SET_FIELD_END + return 1; +} + + +/// Parses a delim-separated string. +/// Starts parsing at startoff and fills the pos array with position pairs. +/// out_pos[0] and out_pos[1] are the start and end of line. +/// Other position pairs are the start and end of fields. +/// Returns the number of fields found or -1 if an error occurs. +/// +/// out_pos can be NULL. +/// If a line terminator is found, the end position is placed there. +/// out_pos[2] and out_pos[3] for the first field, out_pos[4] and out_pos[5] +/// for the seconds field and so on. +/// Unfilled positions are set to -1. +/// +/// @param str String to parse +/// @param len Length of the string +/// @param startoff Where to start parsing +/// @param delim Field delimiter +/// @param out_pos Array of resulting positions +/// @param npos Size of the pos array +/// @param opt Options that determine the parsing behaviour +/// @return Number of fields found in the string or -1 if an error occured +int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, int npos, enum e_svopt opt) +{ + struct s_svstate sv; + int count; + + // initialize + if( out_pos == NULL ) npos = 0; + for( count = 0; count < npos; ++count ) + out_pos[count] = -1; + sv.str = str; + sv.len = len; + sv.off = startoff; + sv.opt = opt; + sv.delim = delim; + sv.done = false; + + // parse + count = 0; + if( npos > 0 ) out_pos[0] = startoff; + while( !sv.done ) + { + ++count; + if( sv_parse_next(&sv) <= 0 ) + return -1;// error + if( npos > count*2 ) out_pos[count*2] = sv.start; + if( npos > count*2+1 ) out_pos[count*2+1] = sv.end; + } + if( npos > 1 ) out_pos[1] = sv.off; return count; } diff --git a/src/common/strlib.h b/src/common/strlib.h index 3f4f984cf..bbc2c6105 100644 --- a/src/common/strlib.h +++ b/src/common/strlib.h @@ -4,9 +4,7 @@ #ifndef _STRLIB_H_ #define _STRLIB_H_ -#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" -#endif #include <stdarg.h> #define __USE_GNU // required to enable strnlen on some platforms @@ -78,6 +76,27 @@ typedef enum e_svopt /// Other escape sequences supported by the C compiler. #define SV_ESCAPE_C_SUPPORTED "abtnvfr\?\"'\\" +/// Parse state. +/// The field is [start,end[ +struct s_svstate +{ + const char* str; //< string to parse + int len; //< string length + int off; //< current offset in the string + int start; //< where the field starts + int end; //< where the field ends + enum e_svopt opt; //< parse options + char delim; //< field delimiter + bool done; //< if all the text has been parsed +}; + +/// Parses a single field in a delim-separated string. +/// The delimiter after the field is skipped. +/// +/// @param sv Parse state +/// @return 1 if a field was parsed, 0 if done, -1 on error. +int sv_parse_next(struct s_svstate* sv); + /// Parses a delim-separated string. /// Starts parsing at startoff and fills the pos array with position pairs. /// out_pos[0] and out_pos[1] are the start and end of line. diff --git a/src/common/timer.c b/src/common/timer.c index 86e148ee3..05c53b8a3 100644 --- a/src/common/timer.c +++ b/src/common/timer.c @@ -241,7 +241,7 @@ static int acquire_timer(void) /// Starts a new timer that is deleted once it expires (single-use). /// Returns the timer's id. -int add_timer(unsigned int tick, TimerFunc func, int id, intptr data) +int add_timer(unsigned int tick, TimerFunc func, int id, intptr_t data) { int tid; @@ -259,7 +259,7 @@ int add_timer(unsigned int tick, TimerFunc func, int id, intptr data) /// Starts a new timer that automatically restarts itself (infinite loop until manually removed). /// Returns the timer's id, or INVALID_TIMER if it fails. -int add_timer_interval(unsigned int tick, TimerFunc func, int id, intptr data, int interval) +int add_timer_interval(unsigned int tick, TimerFunc func, int id, intptr_t data, int interval) { int tid; diff --git a/src/common/timer.h b/src/common/timer.h index 354a71113..a615a5874 100644 --- a/src/common/timer.h +++ b/src/common/timer.h @@ -4,9 +4,7 @@ #ifndef _TIMER_H_ #define _TIMER_H_ -#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" -#endif #define DIFF_TICK(a,b) ((int)((a)-(b))) @@ -19,7 +17,7 @@ // Struct declaration -typedef int (*TimerFunc)(int tid, unsigned int tick, int id, intptr data); +typedef int (*TimerFunc)(int tid, unsigned int tick, int id, intptr_t data); struct TimerData { unsigned int tick; @@ -30,7 +28,7 @@ struct TimerData { // general-purpose storage int id; - intptr data; + intptr_t data; }; // Function prototype declaration @@ -38,8 +36,8 @@ struct TimerData { unsigned int gettick(void); unsigned int gettick_nocache(void); -int add_timer(unsigned int tick, TimerFunc func, int id, intptr data); -int add_timer_interval(unsigned int tick, TimerFunc func, int id, intptr data, int interval); +int add_timer(unsigned int tick, TimerFunc func, int id, intptr_t data); +int add_timer_interval(unsigned int tick, TimerFunc func, int id, intptr_t data, int interval); const struct TimerData* get_timer(int tid); int delete_timer(int tid, TimerFunc func); diff --git a/src/common/utils.h b/src/common/utils.h index 2fe078615..8e39f2655 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -4,10 +4,7 @@ #ifndef _UTILS_H_ #define _UTILS_H_ -#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" -#endif - #include <stdio.h> // FILE* // generate a hex dump of the first 'length' bytes of 'buffer' diff --git a/src/login/CMakeLists.txt b/src/login/CMakeLists.txt new file mode 100644 index 000000000..afa4e5f20 --- /dev/null +++ b/src/login/CMakeLists.txt @@ -0,0 +1,12 @@ + +# +# setup +# +set( LOGIN_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} ) + + +# +# targets +# +add_subdirectory( txt ) +add_subdirectory( sql ) diff --git a/src/login/Makefile.in b/src/login/Makefile.in index c153d95b3..fa1933964 100644 --- a/src/login/Makefile.in +++ b/src/login/Makefile.in @@ -3,16 +3,20 @@ COMMON_OBJ = ../common/obj_all/core.o ../common/obj_all/socket.o ../common/obj_a ../common/obj_all/db.o ../common/obj_all/plugins.o ../common/obj_all/lock.o \ ../common/obj_all/malloc.o ../common/obj_all/showmsg.o ../common/obj_all/utils.o \ ../common/obj_all/strlib.o ../common/obj_all/grfio.o ../common/obj_all/mapindex.o \ - ../common/obj_all/ers.o ../common/obj_all/md5calc.o + ../common/obj_all/ers.o ../common/obj_all/md5calc.o ../common/obj_all/random.o COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \ ../common/version.h ../common/db.h ../common/plugins.h ../common/lock.h \ ../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h \ ../common/grfio.h ../common/mapindex.h \ - ../common/ers.h ../common/md5calc.h + ../common/ers.h ../common/md5calc.h ../common/random.h COMMON_SQL_OBJ = ../common/obj_sql/sql.o COMMON_SQL_H = ../common/sql.h +MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o +MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h +MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar + LOGIN_OBJ = login.o LOGIN_TXT_OBJ = $(LOGIN_OBJ:%=obj_txt/%) \ obj_txt/account_txt.o obj_txt/ipban_txt.o obj_txt/loginlog_txt.o @@ -22,10 +26,11 @@ LOGIN_H = login.h account.h ipban.h loginlog.h HAVE_MYSQL=@HAVE_MYSQL@ ifeq ($(HAVE_MYSQL),yes) - LOGIN_SERVER_SQL_DEPENDS=obj_sql $(LOGIN_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) + LOGIN_SERVER_SQL_DEPENDS=obj_sql $(LOGIN_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) $(MT19937AR_OBJ) else LOGIN_SERVER_SQL_DEPENDS=needs_mysql endif +LOGIN_SERVER_TXT_DEPENDS=obj_txt $(LOGIN_TXT_OBJ) $(COMMON_OBJ) $(MT19937AR_OBJ) @SET_MAKE@ @@ -63,19 +68,25 @@ obj_sql: test -d obj_sql || mkdir obj_sql #executables -login-server: $(LOGIN_TXT_OBJ) $(COMMON_OBJ) - @CC@ @LDFLAGS@ -o ../../login-server@EXEEXT@ $(LOGIN_TXT_OBJ) $(COMMON_OBJ) @LIBS@ +login-server: $(LOGIN_SERVER_TXT_DEPENDS) + @CC@ @LDFLAGS@ -o ../../login-server@EXEEXT@ $(LOGIN_TXT_OBJ) $(COMMON_OBJ) $(MT19937AR_OBJ) @LIBS@ login-server_sql: $(LOGIN_SERVER_SQL_DEPENDS) - @CC@ @LDFLAGS@ -o ../../login-server_sql@EXEEXT@ $(LOGIN_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) @LIBS@ @MYSQL_LIBS@ + @CC@ @LDFLAGS@ -o ../../login-server_sql@EXEEXT@ $(LOGIN_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) $(MT19937AR_OBJ) @LIBS@ @MYSQL_LIBS@ # login object files -obj_txt/%.o: %.c $(LOGIN_H) $(COMMON_H) - @CC@ @CFLAGS@ -DWITH_TXT @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_txt/%.o: %.c $(LOGIN_H) $(COMMON_H) $(MT19937AR_H) + @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) -DWITH_TXT @CPPFLAGS@ -c $(OUTPUT_OPTION) $< -obj_sql/%.o: %.c $(LOGIN_H) $(COMMON_H) - @CC@ @CFLAGS@ -DWITH_SQL @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_sql/%.o: %.c $(LOGIN_H) $(COMMON_H) $(MT19937AR_H) + @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) -DWITH_SQL @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< -# missing common object files +# missing object files ../common/obj_all/%.o: + @$(MAKE) -C ../common txt + +../common/obj_sql/%.o: @$(MAKE) -C ../common sql + +MT19937AR_OBJ: + @$(MAKE) -C ../../3rdparty/mt19937ar diff --git a/src/login/account_txt.c b/src/login/account_txt.c index 758a2c24e..821e26df5 100644 --- a/src/login/account_txt.c +++ b/src/login/account_txt.c @@ -58,7 +58,7 @@ static bool account_db_txt_iter_next(AccountDBIterator* self, struct mmo_account static bool mmo_auth_fromstr(struct mmo_account* acc, char* str, unsigned int version); static bool mmo_auth_tostr(const struct mmo_account* acc, char* str); static void mmo_auth_sync(AccountDB_TXT* self); -static int mmo_auth_sync_timer(int tid, unsigned int tick, int id, intptr data); +static int mmo_auth_sync_timer(int tid, unsigned int tick, int id, intptr_t data); /// public constructor AccountDB* account_db_txt(void) @@ -183,7 +183,7 @@ static bool account_db_txt_init(AccountDB* self) // initialize data saving timer add_timer_func_list(mmo_auth_sync_timer, "mmo_auth_sync_timer"); - db->save_timer = add_timer_interval(gettick() + AUTH_SAVING_INTERVAL, mmo_auth_sync_timer, 0, (intptr)db, AUTH_SAVING_INTERVAL); + db->save_timer = add_timer_interval(gettick() + AUTH_SAVING_INTERVAL, mmo_auth_sync_timer, 0, (intptr_t)db, AUTH_SAVING_INTERVAL); return true; } @@ -634,7 +634,7 @@ static void mmo_auth_sync(AccountDB_TXT* db) db->auths_before_save = AUTHS_BEFORE_SAVE; } -static int mmo_auth_sync_timer(int tid, unsigned int tick, int id, intptr data) +static int mmo_auth_sync_timer(int tid, unsigned int tick, int id, intptr_t data) { AccountDB_TXT* db = (AccountDB_TXT*)data; diff --git a/src/login/ipban_sql.c b/src/login/ipban_sql.c index ef463905e..c75a1f956 100644 --- a/src/login/ipban_sql.c +++ b/src/login/ipban_sql.c @@ -35,7 +35,7 @@ static Sql* sql_handle = NULL; static int cleanup_timer_id = INVALID_TIMER; static bool ipban_inited = false; -int ipban_cleanup(int tid, unsigned int tick, int id, intptr data); +int ipban_cleanup(int tid, unsigned int tick, int id, intptr_t data); // initialize @@ -246,7 +246,7 @@ void ipban_log(uint32 ip) } // remove expired bans -int ipban_cleanup(int tid, unsigned int tick, int id, intptr data) +int ipban_cleanup(int tid, unsigned int tick, int id, intptr_t data) { if( !login_config.ipban ) return 0;// ipban disabled diff --git a/src/login/login.c b/src/login/login.c index 6d8043baf..e57293a4c 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -101,7 +101,7 @@ struct online_login_data { }; static DBMap* online_db; // int account_id -> struct online_login_data* -static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr data); +static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t data); static void* create_online_user(DBKey key, va_list args) { @@ -138,7 +138,7 @@ void remove_online_user(int account_id) idb_remove(online_db, account_id); } -static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr data) +static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t data) { struct online_login_data* p = (struct online_login_data*)idb_get(online_db, id); if( p != NULL && p->waiting_disconnect == tid && p->account_id == id ) @@ -176,7 +176,7 @@ static int online_data_cleanup_sub(DBKey key, void *data, va_list ap) return 0; } -static int online_data_cleanup(int tid, unsigned int tick, int id, intptr data) +static int online_data_cleanup(int tid, unsigned int tick, int id, intptr_t data) { online_db->foreach(online_db, online_data_cleanup_sub); return 0; @@ -190,7 +190,7 @@ int charif_sendallwos(int sfd, uint8* buf, size_t len) { int i, c; - for( i = 0, c = 0; i < MAX_SERVERS; ++i ) + for( i = 0, c = 0; i < ARRAYLENGTH(server); ++i ) { int fd = server[i].fd; if( session_isValid(fd) && fd != sfd ) @@ -206,10 +206,46 @@ int charif_sendallwos(int sfd, uint8* buf, size_t len) } +/// Initializes a server structure. +void chrif_server_init(int id) +{ + memset(&server[id], 0, sizeof(server[id])); + server[id].fd = -1; +} + + +/// Destroys a server structure. +void chrif_server_destroy(int id) +{ + if( server[id].fd != -1 ) + { + do_close(server[id].fd); + server[id].fd = -1; + } +} + + +/// Resets all the data related to a server. +void chrif_server_reset(int id) +{ + online_db->foreach(online_db, online_db_setoffline, id); //Set all chars from this char server to offline. + chrif_server_destroy(id); + chrif_server_init(id); +} + + +/// Called when the connection to Char Server is disconnected. +void chrif_on_disconnect(int id) +{ + ShowStatus("Char-server '%s' has disconnected.\n", server[id].name); + chrif_server_reset(id); +} + + //----------------------------------------------------- // periodic ip address synchronization //----------------------------------------------------- -static int sync_ip_addresses(int tid, unsigned int tick, int id, intptr data) +static int sync_ip_addresses(int tid, unsigned int tick, int id, intptr_t data) { uint8 buf[2]; ShowInfo("IP Sync in progress...\n"); @@ -381,9 +417,10 @@ int parse_fromchar(int fd) uint32 ipl; char ip[16]; - ARR_FIND( 0, MAX_SERVERS, id, server[id].fd == fd ); - if( id == MAX_SERVERS ) + ARR_FIND( 0, ARRAYLENGTH(server), id, server[id].fd == fd ); + if( id == ARRAYLENGTH(server) ) {// not a char server + ShowDebug("parse_fromchar: Disconnecting invalid session #%d (is not a char-server)\n", fd); set_eof(fd); do_close(fd); return 0; @@ -391,11 +428,9 @@ int parse_fromchar(int fd) if( session[fd]->flag.eof ) { - ShowStatus("Char-server '%s' has disconnected.\n", server[id].name); - online_db->foreach(online_db, online_db_setoffline, id); //Set all chars from this char server to offline. - memset(&server[id], 0, sizeof(struct mmo_char_server)); - server[id].fd = -1; do_close(fd); + server[id].fd = -1; + chrif_on_disconnect(id); return 0; } @@ -424,8 +459,9 @@ int parse_fromchar(int fd) RFIFOSKIP(fd,23); node = (struct auth_node*)idb_get(auth_db, account_id); - if( node != NULL && - node->account_id == account_id && + if( runflag == LOGINSERVER_ST_RUNNING && + node != NULL && + node->account_id == account_id && node->login_id1 == login_id1 && node->login_id2 == login_id2 && node->sex == sex_num2str(sex) /*&& @@ -1059,6 +1095,16 @@ void login_auth_ok(struct login_session_data* sd) struct auth_node* node; int i; + if( runflag != LOGINSERVER_ST_RUNNING ) + { + // players can only login while running + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x81; + WFIFOB(fd,2) = 1;// server closed + WFIFOSET(fd,3); + return; + } + if( sd->level < login_config.min_level_to_connect ) { ShowStatus("Connection refused: the minimum GM level for connection is %d (account: %s, GM level: %d).\n", login_config.min_level_to_connect, sd->userid, sd->level); @@ -1070,8 +1116,8 @@ void login_auth_ok(struct login_session_data* sd) } server_num = 0; - for( i = 0; i < MAX_SERVERS; ++i ) - if( session_isValid(server[i].fd) ) + for( i = 0; i < ARRAYLENGTH(server); ++i ) + if( session_isActive(server[i].fd) ) server_num++; if( server_num == 0 ) @@ -1133,7 +1179,7 @@ void login_auth_ok(struct login_session_data* sd) memset(WFIFOP(fd,20), 0, 24); WFIFOW(fd,44) = 0; // unknown WFIFOB(fd,46) = sex_str2num(sd->sex); - for( i = 0, n = 0; i < MAX_SERVERS; ++i ) + for( i = 0, n = 0; i < ARRAYLENGTH(server); ++i ) { if( !session_isValid(server[i].fd) ) continue; @@ -1404,7 +1450,11 @@ int parse_login(int fd) login_log(session[fd]->client_addr, sd->userid, 100, message); result = mmo_auth(sd); - if( result == -1 && sd->sex == 'S' && sd->account_id < MAX_SERVERS && server[sd->account_id].fd == -1 ) + if( runflag == LOGINSERVER_ST_RUNNING && + result == -1 && + sd->sex == 'S' && + sd->account_id >= 0 && sd->account_id < ARRAYLENGTH(server) && + !session_isValid(server[sd->account_id].fd) ) { ShowStatus("Connection of the char-server '%s' accepted.\n", server_name); safestrncpy(server[sd->account_id].name, server_name, sizeof(server[sd->account_id].name)); @@ -1592,7 +1642,7 @@ static AccountDB* get_account_engine(void) //-------------------------------------- void do_final(void) { - int i, fd; + int i; login_log(0, "login server", 100, "login server shutdown"); ShowStatus("Terminating...\n"); @@ -1614,15 +1664,15 @@ void do_final(void) accounts = NULL; // destroyed in account_engines online_db->destroy(online_db, NULL); auth_db->destroy(auth_db, NULL); + + for( i = 0; i < ARRAYLENGTH(server); ++i ) + chrif_server_destroy(i); - for (i = 0; i < MAX_SERVERS; i++) { - if ((fd = server[i].fd) >= 0) { - memset(&server[i], 0, sizeof(struct mmo_char_server)); - server[i].fd = -1; - do_close(fd); - } + if( login_fd != -1 ) + { + do_close(login_fd); + login_fd = -1; } - do_close(login_fd); ShowStatus("Finished.\n"); } @@ -1640,6 +1690,24 @@ void set_server_type(void) SERVER_TYPE = ATHENA_SERVER_LOGIN; } + +/// Called when a terminate signal is received. +void do_shutdown(void) +{ + if( runflag != LOGINSERVER_ST_SHUTDOWN ) + { + int id; + runflag = LOGINSERVER_ST_SHUTDOWN; + ShowStatus("Shutting down...\n"); + // TODO proper shutdown procedure; kick all characters, wait for acks, ... [FlavioJS] + for( id = 0; id < ARRAYLENGTH(server); ++id ) + chrif_server_reset(id); + flush_fifos(); + runflag = CORE_ST_STOP; + } +} + + //------------------------------ // Login server initialization //------------------------------ @@ -1657,9 +1725,9 @@ int do_init(int argc, char** argv) login_lan_config_read((argc > 2) ? argv[2] : LAN_CONF_NAME); srand((unsigned int)time(NULL)); - - for( i = 0; i < MAX_SERVERS; i++ ) - server[i].fd = -1; + + for( i = 0; i < ARRAYLENGTH(server); ++i ) + chrif_server_init(i); // initialize logging if( login_config.log_login ) @@ -1713,6 +1781,12 @@ int do_init(int argc, char** argv) // server port open & binding login_fd = make_listen_bind(login_config.login_ip, login_config.login_port); + + if( runflag != CORE_ST_STOP ) + { + shutdown_callback = do_shutdown; + runflag = LOGINSERVER_ST_RUNNING; + } ShowStatus("The login-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %u).\n\n", login_config.login_port); login_log(0, "login server", 100, "login server started"); diff --git a/src/login/login.h b/src/login/login.h index f338a09e1..07f05f18b 100644 --- a/src/login/login.h +++ b/src/login/login.h @@ -5,6 +5,14 @@ #define _LOGIN_H_ #include "../common/mmo.h" // NAME_LENGTH,SEX_* +#include "../common/core.h" // CORE_ST_LAST + +enum E_LOGINSERVER_ST +{ + LOGINSERVER_ST_RUNNING = CORE_ST_LAST, + LOGINSERVER_ST_SHUTDOWN, + LOGINSERVER_ST_LAST +}; #define LOGIN_CONF_NAME "conf/login_athena.conf" #define LAN_CONF_NAME "conf/subnet_athena.conf" diff --git a/src/login/sql/CMakeLists.txt b/src/login/sql/CMakeLists.txt new file mode 100644 index 000000000..ac7d464c9 --- /dev/null +++ b/src/login/sql/CMakeLists.txt @@ -0,0 +1,43 @@ + +# +# login sql +# +if( HAVE_common_sql ) +message( STATUS "Creating target login-server_sql" ) +set( SQL_LOGIN_HEADERS + "${LOGIN_SOURCE_DIR}/account.h" + "${LOGIN_SOURCE_DIR}/ipban.h" + "${LOGIN_SOURCE_DIR}/login.h" + "${LOGIN_SOURCE_DIR}/loginlog.h" + ) +set( SQL_LOGIN_SOURCES + "${LOGIN_SOURCE_DIR}/account_sql.c" + "${LOGIN_SOURCE_DIR}/ipban_sql.c" + "${LOGIN_SOURCE_DIR}/login.c" + "${LOGIN_SOURCE_DIR}/loginlog_sql.c" + ) +set( DEPENDENCIES common_sql ) +set( LIBRARIES ${GLOBAL_LIBRARIES} ) +set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ) +set( DEFINITIONS ${GLOBAL_DEFINITIONS} WITH_SQL ) +set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ${SQL_LOGIN_HEADERS} ${SQL_LOGIN_SOURCES} ) +source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ) +source_group( login FILES ${SQL_LOGIN_HEADERS} ${SQL_LOGIN_SOURCES} ) +include_directories( ${INCLUDE_DIRS} ) +add_executable( login-server_sql ${SOURCE_FILES} ) +add_dependencies( login-server_sql ${DEPENDENCIES} ) +target_link_libraries( login-server_sql ${LIBRARIES} ${DEPENDENCIES} ) +set_target_properties( login-server_sql PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" ) +if( WITH_COMPONENT_RUNTIME ) + cpack_add_component( Runtime_loginserver_sql DESCRIPTION "login-server (sql version)" DISPLAY_NAME "login-server_sql" GROUP Runtime ) + install( TARGETS login-server_sql + DESTINATION "." + COMPONENT Runtime_loginserver_sql ) +endif() +message( STATUS "Creating target login-server_sql - done" ) +set( HAVE_login-server_sql ON CACHE BOOL "login-server_sql target is available" ) +mark_as_advanced( HAVE_login-server_sql ) +else() +message( STATUS "Skipping target login-server_sql (requires common_sql)" ) +unset( HAVE_login-server_sql CACHE ) +endif() diff --git a/src/login/txt/CMakeLists.txt b/src/login/txt/CMakeLists.txt new file mode 100644 index 000000000..9d57103e9 --- /dev/null +++ b/src/login/txt/CMakeLists.txt @@ -0,0 +1,43 @@ + +# +# login txt +# +if( HAVE_common_base ) +message( STATUS "Creating target login-server" ) +set( TXT_LOGIN_HEADERS + "${LOGIN_SOURCE_DIR}/account.h" + "${LOGIN_SOURCE_DIR}/ipban.h" + "${LOGIN_SOURCE_DIR}/login.h" + "${LOGIN_SOURCE_DIR}/loginlog.h" + ) +set( TXT_LOGIN_SOURCES + "${LOGIN_SOURCE_DIR}/account_txt.c" + "${LOGIN_SOURCE_DIR}/ipban_txt.c" + "${LOGIN_SOURCE_DIR}/login.c" + "${LOGIN_SOURCE_DIR}/loginlog_txt.c" + ) +set( DEPENDENCIES common_base ) +set( LIBRARIES ${GLOBAL_LIBRARIES} ) +set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ) +set( DEFINITIONS ${GLOBAL_DEFINITIONS} WITH_TXT ) +set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${TXT_LOGIN_HEADERS} ${TXT_LOGIN_SOURCES} ) +source_group( common FILES ${COMMON_BASE_HEADERS} ) +source_group( login FILES ${TXT_LOGIN_HEADERS} ${TXT_LOGIN_SOURCES} ) +include_directories( ${INCLUDE_DIRS} ) +add_executable( login-server ${SOURCE_FILES} ) +add_dependencies( login-server ${DEPENDENCIES} ) +target_link_libraries( login-server ${LIBRARIES} ${DEPENDENCIES} ) +set_target_properties( login-server PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" ) +if( WITH_COMPONENT_RUNTIME ) + cpack_add_component( Runtime_loginserver_txt DESCRIPTION "login-server (txt version)" DISPLAY_NAME "login-server" GROUP Runtime ) + install( TARGETS login-server + DESTINATION "." + COMPONENT Runtime_loginserver_txt ) +endif() +message( STATUS "Creating target login-server - done" ) +set( HAVE_login-server ON CACHE BOOL "login-server target is available" ) +mark_as_advanced( HAVE_login-server ) +else() +message( STATUS "Skipping target login-server (requires common_base)" ) +unset( HAVE_login-server CACHE ) +endif() diff --git a/src/map/CMakeLists.txt b/src/map/CMakeLists.txt new file mode 100644 index 000000000..9199702be --- /dev/null +++ b/src/map/CMakeLists.txt @@ -0,0 +1,12 @@ + +# +# setup +# +set( MAP_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} ) + + +# +# targets +# +add_subdirectory( txt ) +add_subdirectory( sql ) diff --git a/src/map/Makefile.in b/src/map/Makefile.in index 7070a0a9d..09e92dde2 100644 --- a/src/map/Makefile.in +++ b/src/map/Makefile.in @@ -3,16 +3,22 @@ COMMON_OBJ = ../common/obj_all/core.o ../common/obj_all/socket.o ../common/obj_a ../common/obj_all/db.o ../common/obj_all/plugins.o ../common/obj_all/lock.o \ ../common/obj_all/nullpo.o ../common/obj_all/malloc.o ../common/obj_all/showmsg.o \ ../common/obj_all/utils.o ../common/obj_all/strlib.o ../common/obj_all/grfio.o \ - ../common/obj_all/mapindex.o ../common/obj_all/ers.o ../common/obj_all/md5calc.o + ../common/obj_all/mapindex.o ../common/obj_all/ers.o ../common/obj_all/md5calc.o \ + ../common/obj_all/random.o COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h \ ../common/db.h ../common/plugins.h ../common/lock.h \ ../common/nullpo.h ../common/malloc.h ../common/showmsg.h \ ../common/utils.h ../common/strlib.h ../common/grfio.h \ - ../common/mapindex.h ../common/ers.h ../common/md5calc.h + ../common/mapindex.h ../common/ers.h ../common/md5calc.h \ + ../common/random.h COMMON_SQL_OBJ = ../common/obj_sql/sql.o COMMON_SQL_H = ../common/sql.h +MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o +MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h +MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar + MAP_OBJ = map.o chrif.o clif.o pc.o status.o npc.o \ npc_chat.o chat.o path.o itemdb.o mob.o script.o \ storage.o skill.o atcommand.o battle.o battleground.o \ @@ -38,6 +44,7 @@ else ALL_TARGET=txt SQL_DEPENDS=needs_mysql endif +TXT_DEPENDS=map-server HAVE_PCRE=@HAVE_PCRE@ ifeq ($(HAVE_PCRE),yes) @@ -53,7 +60,7 @@ endif all: $(ALL_DEPENDS) -txt: map-server +txt: $(TXT_DEPENDS) sql: $(SQL_DEPENDS) @@ -87,21 +94,24 @@ obj_sql: # executables map-server: obj_txt $(MAP_TXT_OBJ) $(COMMON_OBJ) - @CC@ @LDFLAGS@ -o ../../map-server@EXEEXT@ $(MAP_TXT_OBJ) $(COMMON_OBJ) @LIBS@ @PCRE_LIBS@ + @CC@ @LDFLAGS@ -o ../../map-server@EXEEXT@ $(MAP_TXT_OBJ) $(COMMON_OBJ) $(MT19937AR_OBJ) @LIBS@ @PCRE_LIBS@ map-server_sql: obj_sql $(MAP_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) - @CC@ @LDFLAGS@ -o ../../map-server_sql@EXEEXT@ $(MAP_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@ + @CC@ @LDFLAGS@ -o ../../map-server_sql@EXEEXT@ $(MAP_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) $(MT19937AR_OBJ) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@ # map object files -obj_txt/%.o: %.c $(MAP_H) $(COMMON_H) - @CC@ @CFLAGS@ $(PCRE_CFLAGS) -DTXT_ONLY @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_txt/%.o: %.c $(MAP_H) $(COMMON_H) $(MT19937AR_H) + @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) $(PCRE_CFLAGS) -DTXT_ONLY @CPPFLAGS@ -c $(OUTPUT_OPTION) $< -obj_sql/%.o: %.c $(MAP_H) $(COMMON_H) $(COMMON_SQL_H) - @CC@ @CFLAGS@ $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_sql/%.o: %.c $(MAP_H) $(COMMON_H) $(COMMON_SQL_H) $(MT19937AR_H) + @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< -# missing common object files +# missing object files ../common/obj_all/%.o: @$(MAKE) -C ../common txt ../common/obj_sql/%.o: @$(MAKE) -C ../common sql + +MT19937AR_OBJ: + @$(MAKE) -C ../../3rdparty/mt19937ar diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 664430b18..32c2cabf7 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -3988,23 +3988,9 @@ ACMD_FUNC(agitend2) *------------------------------------------*/ ACMD_FUNC(mapexit) { - struct map_session_data* pl_sd; - struct s_mapiterator* iter; - nullpo_retr(-1, sd); - iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) - if (sd->status.account_id != pl_sd->status.account_id) - clif_GM_kick(NULL, pl_sd); - mapit_free(iter); - - clif_GM_kick(NULL, sd); - - flush_fifos(); - - runflag = 0; - + do_shutdown(); return 0; } @@ -7098,9 +7084,9 @@ ACMD_FUNC(mobinfo) if (mob->mvpitem[i].p > 0) { j++; if (j == 1) - sprintf(atcmd_output2, " %s %02.02f%%", item_data->name, (float)mob->mvpitem[i].p / 100); + sprintf(atcmd_output2, " %s %02.02f%%", item_data->jname, (float)mob->mvpitem[i].p / 100); else - sprintf(atcmd_output2, " - %s %02.02f%%", item_data->name, (float)mob->mvpitem[i].p / 100); + sprintf(atcmd_output2, " - %s %02.02f%%", item_data->jname, (float)mob->mvpitem[i].p / 100); strcat(atcmd_output, atcmd_output2); } } @@ -7117,7 +7103,7 @@ ACMD_FUNC(mobinfo) * @showmobs by KarLaeda * => For 5 sec displays the mobs on minimap *------------------------------------------*/ -int atshowmobs_timer(int tid, unsigned int tick, int id, intptr data) +int atshowmobs_timer(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data* sd = map_id2sd(id); if( sd == NULL ) diff --git a/src/map/battle.c b/src/map/battle.c index aea2f2da4..ca5662dd7 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -154,7 +154,7 @@ struct delay_damage { unsigned short attack_type; }; -int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr data) +int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) { struct delay_damage *dat = (struct delay_damage *)data; struct block_list *target = map_id2bl(dat->target); @@ -208,7 +208,7 @@ int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, dat->distance = distance_bl(src, target)+10; //Attack should connect regardless unless you teleported. if (src->type != BL_PC && amotion > 1000) amotion = 1000; //Aegis places a damage-delay cap of 1 sec to non player attacks. [Skotlex] - add_timer(tick+amotion, battle_delay_damage_sub, src->id, (intptr)dat); + add_timer(tick+amotion, battle_delay_damage_sub, src->id, (intptr_t)dat); return 0; } @@ -1620,7 +1620,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo case AS_SPLASHER: skillratio += 400+50*skill_lv; if(sd) - skillratio += 30 * pc_checkskill(sd,AS_POISONREACT); + skillratio += 20 * pc_checkskill(sd,AS_POISONREACT); break; case ASC_BREAKER: skillratio += 100*skill_lv-100; diff --git a/src/map/battle.h b/src/map/battle.h index 8d014c5f9..d54d49c0a 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -72,20 +72,19 @@ struct block_list* battle_getenemy(struct block_list *target, int type, int rang int battle_gettarget(struct block_list *bl); int battle_getcurrentskill(struct block_list *bl); -//New definitions [Skotlex] -#define BCT_ENEMY 0x020000 -//This should be (~BCT_ENEMY&BCT_ALL) -#define BCT_NOENEMY 0x1d0000 -#define BCT_PARTY 0x040000 -//This should be (~BCT_PARTY&BCT_ALL) -#define BCT_NOPARTY 0x1b0000 -#define BCT_GUILD 0x080000 -//This should be (~BCT_GUILD&BCT_ALL) -#define BCT_NOGUILD 0x170000 -#define BCT_ALL 0x1f0000 -#define BCT_NOONE 0x000000 -#define BCT_SELF 0x010000 -#define BCT_NEUTRAL 0x100000 +enum e_battle_check_target +{//New definitions [Skotlex] + BCT_ENEMY = 0x020000, + BCT_NOENEMY = 0x1d0000, //This should be (~BCT_ENEMY&BCT_ALL) + BCT_PARTY = 0x040000, + BCT_NOPARTY = 0x1b0000, //This should be (~BCT_PARTY&BCT_ALL) + BCT_GUILD = 0x080000, + BCT_NOGUILD = 0x170000, //This should be (~BCT_GUILD&BCT_ALL) + BCT_ALL = 0x1f0000, + BCT_NOONE = 0x000000, + BCT_SELF = 0x010000, + BCT_NEUTRAL = 0x100000, +}; #define is_boss(bl) (status_get_mode(bl)&MD_BOSS) // Can refine later [Aru] diff --git a/src/map/battleground.c b/src/map/battleground.c index 13f62a042..b456a868a 100644 --- a/src/map/battleground.c +++ b/src/map/battleground.c @@ -236,7 +236,7 @@ int bg_send_xy_timer_sub(DBKey key, void *data, va_list ap) return 0; } -int bg_send_xy_timer(int tid, unsigned int tick, int id, intptr data) +int bg_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data) { bg_team_db->foreach(bg_team_db, bg_send_xy_timer_sub, tick); return 0; diff --git a/src/map/buyingstore.c b/src/map/buyingstore.c index 5b9734819..94f390c10 100644 --- a/src/map/buyingstore.c +++ b/src/map/buyingstore.c @@ -145,7 +145,7 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha if( i ) {// duplicate check. as the client does this too, only malicious intent should be caught here - ARR_FIND( 0, i, listidx, sd->buyingstore.items[i].nameid == nameid ); + ARR_FIND( 0, i, listidx, sd->buyingstore.items[listidx].nameid == nameid ); if( listidx != i ) {// duplicate ShowWarning("buyingstore_create: Found duplicate item on buying list (nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", nameid, amount, sd->status.account_id, sd->status.char_id); diff --git a/src/map/chrif.c b/src/map/chrif.c index c4eeea3d9..a14200a36 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -31,6 +31,8 @@ #include <sys/types.h> #include <time.h> +static int check_connect_char_server(int tid, unsigned int tick, int id, intptr_t data); + static struct eri *auth_db_ers; //For reutilizing player login structures. static DBMap* auth_db; // int id -> struct auth_node* @@ -94,7 +96,7 @@ static const int packet_len_table[0x3d] = { // U - used, F - free //2b27: Incoming, chrif_authfail -> 'client authentication failed' int chrif_connected = 0; -int char_fd = 0; //Using 0 instead of -1 is safer against crashes. [Skotlex] +int char_fd = -1; int srvinfo; static char char_ip_str[128]; static uint32 char_ip = 0; @@ -110,6 +112,28 @@ int other_mapserver_count=0; //Holds count of how many other map servers are onl //This define should spare writing the check in every function. [Skotlex] #define chrif_check(a) { if(!chrif_isconnected()) return a; } + +/// Resets all the data. +void chrif_reset(void) +{ + // TODO kick everyone out and reset everything [FlavioJS] + exit(EXIT_FAILURE); +} + + +/// Checks the conditions for the server to stop. +/// Releases the cookie when all characters are saved. +/// If all the conditions are met, it stops the core loop. +void chrif_check_shutdown(void) +{ + if( runflag != MAPSERVER_ST_SHUTDOWN ) + return; + if( auth_db->size(auth_db) > 0 ) + return; + runflag = CORE_ST_STOP; +} + + struct auth_node* chrif_search(int account_id) { return (struct auth_node*)idb_get(auth_db, account_id); @@ -244,9 +268,8 @@ int chrif_save(struct map_session_data *sd, int flag) { nullpo_retr(-1, sd); - if (!flag) //The flag check is needed to prevent 'nosave' taking effect when a jailed player logs out. - pc_makesavestatus(sd); - + pc_makesavestatus(sd); + if (flag && sd->state.active) //Store player data which is quitting. { //FIXME: SC are lost if there's no connection at save-time because of the way its related data is cleared immediately after this function. [Skotlex] @@ -363,6 +386,7 @@ int chrif_removemap(int fd) static void chrif_save_ack(int fd) { chrif_auth_delete(RFIFOL(fd,2), RFIFOL(fd,6), ST_LOGOUT); + chrif_check_shutdown(); } // request to move a character between mapservers @@ -472,19 +496,13 @@ static int chrif_reconnect(DBKey key,void *data,va_list ap) return 0; } -/*========================================== - * - *------------------------------------------*/ -int chrif_sendmapack(int fd) -{ - if (RFIFOB(fd,2)) { - ShowFatalError("chrif : send map list to char server failed %d\n", RFIFOB(fd,2)); - exit(EXIT_FAILURE); - } - memcpy(wisp_server_name, RFIFOP(fd,3), NAME_LENGTH); - ShowStatus("Map sending complete. Map Server is now online.\n"); +/// Called when all the connection steps are completed. +void chrif_on_ready(void) +{ + ShowStatus("Map Server is now online.\n"); chrif_state = 2; + chrif_check_shutdown(); //If there are players online, send them to the char-server. [Skotlex] send_users_tochar(); @@ -494,7 +512,21 @@ int chrif_sendmapack(int fd) //Re-save any storages that were modified in the disconnection time. [Skotlex] do_reconnect_storage(); +} + +/*========================================== + * + *------------------------------------------*/ +int chrif_sendmapack(int fd) +{ + if (RFIFOB(fd,2)) { + ShowFatalError("chrif : send map list to char server failed %d\n", RFIFOB(fd,2)); + exit(EXIT_FAILURE); + } + + memcpy(wisp_server_name, RFIFOP(fd,3), NAME_LENGTH); + chrif_on_ready(); return 0; } @@ -592,7 +624,8 @@ void chrif_authok(int fd) } sd = node->sd; - if(node->char_dat == NULL && + if( runflag == MAPSERVER_ST_RUNNING && + node->char_dat == NULL && node->account_id == account_id && node->char_id == char_id && node->login_id1 == login_id1 ) @@ -661,7 +694,7 @@ int auth_db_cleanup_sub(DBKey key,void *data,va_list ap) return 0; } -int auth_db_cleanup(int tid, unsigned int tick, int id, intptr data) +int auth_db_cleanup(int tid, unsigned int tick, int id, intptr_t data) { if(!chrif_isconnected()) return 0; auth_db->foreach(auth_db, auth_db_cleanup_sub); @@ -838,7 +871,7 @@ int chrif_changedsex(int fd) if ((sd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER) { // remove specifical skills of Bard classes for(i = 315; i <= 322; i++) { - if (sd->status.skill[i].id > 0 && !sd->status.skill[i].flag) { + if (sd->status.skill[i].id > 0 && sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) { sd->status.skill_point += sd->status.skill[i].lv; sd->status.skill[i].id = 0; sd->status.skill[i].lv = 0; @@ -846,7 +879,7 @@ int chrif_changedsex(int fd) } // remove specifical skills of Dancer classes for(i = 323; i <= 330; i++) { - if (sd->status.skill[i].id > 0 && !sd->status.skill[i].flag) { + if (sd->status.skill[i].id > 0 && sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) { sd->status.skill_point += sd->status.skill[i].lv; sd->status.skill[i].id = 0; sd->status.skill[i].lv = 0; @@ -1292,22 +1325,22 @@ int chrif_char_online(struct map_session_data *sd) return 0; } -int chrif_disconnect(int fd) + +/// Called when the connection to Char Server is disconnected. +void chrif_on_disconnect(void) { - if(fd == char_fd) { - char_fd = 0; - ShowWarning("Map Server disconnected from Char Server.\n\n"); - chrif_connected = 0; - - other_mapserver_count=0; //Reset counter. We receive ALL maps from all map-servers on reconnect. - map_eraseallipport(); + if( chrif_connected != 1 ) + ShowWarning("Connection to Char Server lost.\n\n"); + chrif_connected = 0; + + other_mapserver_count = 0; //Reset counter. We receive ALL maps from all map-servers on reconnect. + map_eraseallipport(); - //Attempt to reconnect in a second. [Skotlex] - add_timer(gettick() + 1000, check_connect_char_server, 0, 0); - } - return 0; + //Attempt to reconnect in a second. [Skotlex] + add_timer(gettick() + 1000, check_connect_char_server, 0, 0); } + void chrif_update_ip(int fd) { uint32 new_ip; @@ -1352,10 +1385,9 @@ int chrif_parse(int fd) if (session[fd]->flag.eof) { - if (chrif_connected == 1) - chrif_disconnect(fd); - do_close(fd); + char_fd = -1; + chrif_on_disconnect(); return 0; } @@ -1393,7 +1425,7 @@ int chrif_parse(int fd) case 0x2afb: chrif_sendmapack(fd); break; case 0x2afd: chrif_authok(fd); break; case 0x2b00: map_setusers(RFIFOL(fd,2)); chrif_keepalive(fd); break; - case 0x2b03: clif_charselectok(RFIFOL(fd,2)); break; + case 0x2b03: clif_charselectok(RFIFOL(fd,2), RFIFOB(fd,6)); break; case 0x2b04: chrif_recvmap(fd); break; case 0x2b06: chrif_changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break; case 0x2b09: map_addnickdb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break; @@ -1423,7 +1455,7 @@ int chrif_parse(int fd) return 0; } -int ping_char_server(int tid, unsigned int tick, int id, intptr data) +int ping_char_server(int tid, unsigned int tick, int id, intptr_t data) { chrif_check(-1); chrif_keepalive(char_fd); @@ -1431,7 +1463,7 @@ int ping_char_server(int tid, unsigned int tick, int id, intptr data) } // unused -int send_usercount_tochar(int tid, unsigned int tick, int id, intptr data) +int send_usercount_tochar(int tid, unsigned int tick, int id, intptr_t data) { chrif_check(-1); @@ -1476,7 +1508,7 @@ int send_users_tochar(void) * timer関数 * char鯖との接続を確認し、もし切れていたら再度接続する *------------------------------------------*/ -int check_connect_char_server(int tid, unsigned int tick, int id, intptr data) +static int check_connect_char_server(int tid, unsigned int tick, int id, intptr_t data) { static int displayed = 0; if (char_fd <= 0 || session[char_fd] == NULL) @@ -1491,7 +1523,6 @@ int check_connect_char_server(int tid, unsigned int tick, int id, intptr data) char_fd = make_connection(char_ip, char_port); if (char_fd == -1) { //Attempt to connect later. [Skotlex] - char_fd = 0; return 0; } @@ -1532,8 +1563,11 @@ int auth_db_final(DBKey k,void *d,va_list ap) *------------------------------------------*/ int do_final_chrif(void) { - if (char_fd > 0) + if( char_fd != -1 ) + { do_close(char_fd); + char_fd = -1; + } auth_db->destroy(auth_db, auth_db_final); ers_destroy(auth_db_ers); diff --git a/src/map/chrif.h b/src/map/chrif.h index 9ff5b9a0e..1f11cc6f2 100644 --- a/src/map/chrif.h +++ b/src/map/chrif.h @@ -25,6 +25,7 @@ int chrif_setip(const char* ip); void chrif_setport(uint16 port); int chrif_isconnected(void); +void chrif_check_shutdown(void); extern int chrif_connected; extern int other_mapserver_count; @@ -55,7 +56,6 @@ int send_users_tochar(void); int chrif_char_online(struct map_session_data *sd); int chrif_changesex(struct map_session_data *sd); int chrif_chardisconnect(struct map_session_data *sd); -int check_connect_char_server(int tid, unsigned int tick, int id, intptr data); int chrif_divorce(int partner_id1, int partner_id2); int do_final_chrif(void); diff --git a/src/map/clif.c b/src/map/clif.c index 81ab49799..8d2159823 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -581,10 +581,10 @@ int clif_authfail_fd(int fd, int type) return 0; } -/*========================================== - * - *------------------------------------------*/ -int clif_charselectok(int id) +/// Reply from char-server. +/// Tells the player if it can connect to the char-server to select a character. +/// ok=1 : client disconnects and tries to connect to the char-server +int clif_charselectok(int id, uint8 ok) { struct map_session_data* sd; int fd; @@ -595,7 +595,7 @@ int clif_charselectok(int id) fd = sd->fd; WFIFOHEAD(fd,packet_len(0xb3)); WFIFOW(fd,0) = 0xb3; - WFIFOB(fd,2) = 1; + WFIFOB(fd,2) = ok; WFIFOSET(fd,packet_len(0xb3)); return 0; @@ -700,7 +700,7 @@ int clif_clearunit_area(struct block_list* bl, clr_type type) return 0; } -static int clif_clearunit_delayed_sub(int tid, unsigned int tick, int id, intptr data) +static int clif_clearunit_delayed_sub(int tid, unsigned int tick, int id, intptr_t data) { struct block_list *bl = (struct block_list *)data; clif_clearunit_area(bl, CLR_OUTSIGHT); @@ -713,7 +713,7 @@ int clif_clearunit_delayed(struct block_list* bl, unsigned int tick) struct block_list *tbl; tbl = (struct block_list*)aMalloc(sizeof (struct block_list)); memcpy (tbl, bl, sizeof (struct block_list)); - add_timer(tick, clif_clearunit_delayed_sub, 0, (intptr)tbl); + add_timer(tick, clif_clearunit_delayed_sub, 0, (intptr_t)tbl); return 0; } @@ -1376,6 +1376,12 @@ static void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_ clif_specialeffect(&md->bl,421,AREA); } break; + case BL_PET: + if( vd->head_bottom ) + {// needed to display pet equip properly + clif_pet_equip_area((TBL_PET*)bl); + } + break; } return; } @@ -1415,7 +1421,7 @@ void clif_move(struct unit_data *ud) /*========================================== * Delays the map_quit of a player after they are disconnected. [Skotlex] *------------------------------------------*/ -static int clif_delayquit(int tid, unsigned int tick, int id, intptr data) +static int clif_delayquit(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd = NULL; @@ -4192,7 +4198,7 @@ int clif_skillinfoblock(struct map_session_data *sd) WFIFOW(fd,len+8) = skill_get_sp(id,sd->status.skill[i].lv); WFIFOW(fd,len+10)= skill_get_range2(&sd->bl, id,sd->status.skill[i].lv); safestrncpy((char*)WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH); - if(sd->status.skill[i].flag == 0) + if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) WFIFOB(fd,len+36) = (sd->status.skill[i].lv < skill_tree_get_max(id, sd->status.class_))? 1:0; else WFIFOB(fd,len+36) = 0; @@ -4229,7 +4235,7 @@ int clif_addskill(struct map_session_data *sd, int id ) WFIFOW(fd,10) = skill_get_sp(id,sd->status.skill[id].lv); WFIFOW(fd,12)= skill_get_range2(&sd->bl, id,sd->status.skill[id].lv); safestrncpy((char*)WFIFOP(fd,14), skill_get_name(id), NAME_LENGTH); - if( sd->status.skill[id].flag == 0 ) + if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) WFIFOB(fd,38) = (sd->status.skill[id].lv < skill_tree_get_max(id, sd->status.class_))? 1:0; else WFIFOB(fd,38) = 0; @@ -4279,38 +4285,49 @@ int clif_skillup(struct map_session_data *sd,int skill_num) return 0; } -/*========================================== - * スキル詠唱エフェクトを送信する - * pl: - * 0 = Yellow cast aura - * 1 = Water elemental cast aura - * 2 = Earth elemental cast aura - * 3 = Fire elemental cast aura - * 4 = Wind elemental cast aura - * 5 = Poison elemental cast aura - * 6 = White cast aura - * ? = like 0 - *------------------------------------------*/ -int clif_skillcasting(struct block_list* bl, - int src_id,int dst_id,int dst_x,int dst_y,int skill_num,int pl, int casttime) + +/// Notifies clients, that an object is about to use a skill (ZC_USESKILL_ACK/ZC_USESKILL_ACK2) +/// 013e <src id>.L <dst id>.L <x pos>.W <y pos>.W <skill id>.W <property>.L <delaytime>.L +/// 07fb <src id>.L <dst id>.L <x pos>.W <y pos>.W <skill id>.W <property>.L <delaytime>.L <is disposable>.B +/// property: +/// 0 = Yellow cast aura +/// 1 = Water elemental cast aura +/// 2 = Earth elemental cast aura +/// 3 = Fire elemental cast aura +/// 4 = Wind elemental cast aura +/// 5 = Poison elemental cast aura +/// 6 = Holy elemental cast aura +/// ? = like 0 +/// is disposable: +/// 0 = yellow chat text "[src name] will use skill [skill name]." +/// 1 = no text +void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, int skill_num, int property, int casttime) { +#if PACKETVER < 20091124 + const int cmd = 0x13e; +#else + const int cmd = 0x7fb; +#endif unsigned char buf[32]; - WBUFW(buf,0) = 0x13e; + + WBUFW(buf,0) = cmd; WBUFL(buf,2) = src_id; WBUFL(buf,6) = dst_id; WBUFW(buf,10) = dst_x; WBUFW(buf,12) = dst_y; WBUFW(buf,14) = skill_num; - WBUFL(buf,16) = pl<0?0:pl; //Avoid sending negatives as element [Skotlex] + WBUFL(buf,16) = property<0?0:property; //Avoid sending negatives as element [Skotlex] WBUFL(buf,20) = casttime; +#if PACKETVER >= 20091124 + WBUFB(buf,24) = 1; // isDisposable +#endif + if (disguised(bl)) { - clif_send(buf,packet_len(0x13e), bl, AREA_WOS); + clif_send(buf,packet_len(cmd), bl, AREA_WOS); WBUFL(buf,2) = -src_id; - clif_send(buf,packet_len(0x13e), bl, SELF); + clif_send(buf,packet_len(cmd), bl, SELF); } else - clif_send(buf,packet_len(0x13e), bl, AREA); - - return 0; + clif_send(buf,packet_len(cmd), bl, AREA); } /*========================================== @@ -5821,28 +5838,32 @@ void clif_partyinvitationstate(struct map_session_data* sd) WFIFOSET(fd, packet_len(0x2c9)); } -/*========================================== - * パーティ勧誘 - *------------------------------------------*/ -int clif_party_invite(struct map_session_data *sd,struct map_session_data *tsd) +/// Party invitation request (ZC_REQ_JOIN_GROUP/ZC_PARTY_JOIN_REQ) +/// 00fe <party id>.L <party name>.24B +/// 02c6 <party id>.L <party name>.24B +void clif_party_invite(struct map_session_data *sd,struct map_session_data *tsd) { +#if PACKETVER < 20070821 + const int cmd = 0xfe; +#else + const int cmd = 0x2c6; +#endif int fd; struct party_data *p; - nullpo_ret(sd); - nullpo_ret(tsd); + nullpo_retv(sd); + nullpo_retv(tsd); fd=tsd->fd; if( (p=party_search(sd->status.party_id))==NULL ) - return 0; + return; - WFIFOHEAD(fd,packet_len(0xfe)); - WFIFOW(fd,0)=0xfe; - WFIFOL(fd,2)=sd->status.account_id; // FIXME: This is party_id + WFIFOHEAD(fd,packet_len(cmd)); + WFIFOW(fd,0)=cmd; + WFIFOL(fd,2)=sd->status.party_id; memcpy(WFIFOP(fd,6),p->party.name,NAME_LENGTH); - WFIFOSET(fd,packet_len(0xfe)); - return 0; + WFIFOSET(fd,packet_len(cmd)); } /*========================================== @@ -7643,6 +7664,8 @@ int clif_refresh(struct map_session_data *sd) clif_weather_check(sd); if( sd->chatID ) chat_leavechat(sd,0); + if( sd->state.vending ) + clif_openvending(sd, sd->bl.id, sd->vending); if( pc_issit(sd) ) clif_sitting(&sd->bl); // FIXME: just send to self, not area if( pc_isdead(sd) ) //When you refresh, resend the death packet. @@ -7650,6 +7673,9 @@ int clif_refresh(struct map_session_data *sd) else clif_changed_dir(&sd->bl, SELF); + // unlike vending, resuming buyingstore crashes the client. + buyingstore_close(sd); + #ifndef TXT_ONLY mail_clear(sd); #endif @@ -8371,6 +8397,12 @@ void clif_parse_WantToConnection(int fd, TBL_PC* sd) return; } + if( runflag != MAPSERVER_ST_RUNNING ) + {// not allowed + clif_authfail_fd(fd,1);// server closed + return; + } + //Check for double login. bl = map_id2bl(account_id); if(bl && bl->type != BL_PC) { @@ -10620,12 +10652,12 @@ void clif_parse_PartyInvite2(int fd, struct map_session_data *sd) party_invite(sd, t_sd); } -/*========================================== - * Party invitation reply - * S 00ff <account ID>.L <flag>.L - * S 02c7 <account ID>.L <flag>.B - * flag: 0-reject, 1-accept - *------------------------------------------*/ +/// Party invitation reply (CZ_JOIN_GROUP/CZ_PARTY_JOIN_REQ_ACK) +/// 00ff <party id>.L <flag>.L +/// 02c7 <party id>.L <flag>.B +/// flag: +/// 0 = reject +/// 1 = accept void clif_parse_ReplyPartyInvite(int fd,struct map_session_data *sd) { party_reply_invite(sd,RFIFOL(fd,2),RFIFOL(fd,6)); @@ -11995,6 +12027,11 @@ void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) return; } + if( sd->bl.id == f_sd->bl.id ) + {// adding oneself as friend + return; + } + // @noask [LuzZza] if(f_sd->state.noask) { clif_noask_sub(sd, f_sd, 5); @@ -12037,6 +12074,11 @@ void clif_parse_FriendsListReply(int fd, struct map_session_data *sd) char_id = RFIFOL(fd,6); reply = RFIFOB(fd,10); + if( sd->bl.id == account_id ) + {// adding oneself as friend + return; + } + f_sd = map_id2sd(account_id); //The account id is the same as the bl.id of players. if (f_sd == NULL) return; @@ -12305,10 +12347,8 @@ void clif_parse_FeelSaveOk(int fd,struct map_session_data *sd) sd->menuskill_val = sd->menuskill_id = 0; } -/*========================================== - * Question about Star Glaldiator save map [Komurka] - *------------------------------------------*/ -void clif_parse_ReqFeel(int fd, struct map_session_data *sd, int skilllv) +/// Star Gladiator's Feeling map confirmation prompt (ZC_STARPLACE) +void clif_feel_req(int fd, struct map_session_data *sd, int skilllv) { WFIFOHEAD(fd,packet_len(0x253)); WFIFOW(fd,0)=0x253; @@ -13957,11 +13997,11 @@ int clif_instance(int instance_id, int type, int flag) switch( type ) { case 1: - // S 0x2cb <Instance name>.63B <Standby Position>.W + // S 0x2cb <Instance name>.61B <Standby Position>.W // Required to start the instancing information window on Client // This window re-appear each "refresh" of client automatically until type 4 is send to client. WBUFW(buf,0) = 0x02CB; - memcpy(WBUFP(buf,2),instance[instance_id].name,61); + memcpy(WBUFP(buf,2),instance[instance_id].name,INSTANCE_NAME_LENGTH); WBUFW(buf,63) = flag; clif_send(buf,packet_len(0x02CB),&sd->bl,PARTY); break; @@ -13989,14 +14029,16 @@ int clif_instance(int instance_id, int type, int flag) } clif_send(buf,packet_len(0x02CD),&sd->bl,PARTY); break; - case 5: // R 02CE <message ID>.L + case 5: // S 0x2ce <Message ID>.L + // 0 = Notification (EnterLimitDate update?) // 1 = The Memorial Dungeon expired; it has been destroyed // 2 = The Memorial Dungeon's entry time limit expired; it has been destroyed // 3 = The Memorial Dungeon has been removed. - // 4 = Just remove the window, maybe party/guild leave + // 4 = Create failure (removes the instance window) WBUFW(buf,0) = 0x02CE; WBUFL(buf,2) = flag; + //WBUFL(buf,6) = EnterLimitDate; clif_send(buf,packet_len(0x02CE),&sd->bl,PARTY); break; } @@ -14911,7 +14953,7 @@ static int packetdb_readdb(void) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, -1, -1,107, 6, -1, 7, 7, 22,191, 0, 0, 0, 0, 0, 0, //#0x02C0 - 0, 0, 0, 0, 0, 30, 0, 0, 0, 3, 0, 65, 4, 71, 10, 0, + 0, 0, 0, 0, 0, 30, 30, 0, 0, 3, 0, 65, 4, 71, 10, 0, 0, 0, 0, 0, 29, 0, 6, -1, 10, 10, 3, 0, -1, 32, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 59, 60, 8, 10, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -15018,7 +15060,7 @@ static int packetdb_readdb(void) 6, 2, -1, 4, 4, 4, 4, 8, 8,268, 6, 8, 6, 54, 30, 54, #endif 0, 0, 0, 0, 0, 8, 8, 32, -1, 5, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 14, -1, -1, -1, 8, 0, 0, 0, 26, 0, + 0, 0, 0, 0, 0, 0, 14, -1, -1, -1, 8, 25, 0, 0, 26, 0, //#0x0800 #if PACKETVER < 20091229 -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 20, diff --git a/src/map/clif.h b/src/map/clif.h index 70a7fdce8..0feeb22b5 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -220,7 +220,7 @@ uint16 clif_getport(void); int clif_authok(struct map_session_data *); int clif_authfail_fd(int fd,int type); -int clif_charselectok(int); +int clif_charselectok(int id, uint8 ok); int clif_dropflooritem(struct flooritem_data *); int clif_clearflooritem(struct flooritem_data *,int); @@ -326,7 +326,7 @@ int clif_skillup(struct map_session_data *sd,int skill_num); int clif_addskill(struct map_session_data *sd, int skill); int clif_deleteskill(struct map_session_data *sd, int skill); -int clif_skillcasting(struct block_list* bl,int src_id,int dst_id,int dst_x,int dst_y,int skill_num,int pl,int casttime); +void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, int skill_num, int property, int casttime); int clif_skillcastcancel(struct block_list* bl); int clif_skill_fail(struct map_session_data *sd,int skill_id,int type,int btype); int clif_skill_cooldown(struct map_session_data *sd, int skillid, unsigned int tick); @@ -404,7 +404,7 @@ int clif_movetoattack(struct map_session_data *sd,struct block_list *bl); int clif_party_created(struct map_session_data *sd,int result); int clif_party_member_info(struct party_data *p, struct map_session_data *sd); int clif_party_info(struct party_data *p, struct map_session_data *sd); -int clif_party_invite(struct map_session_data *sd,struct map_session_data *tsd); +void clif_party_invite(struct map_session_data *sd,struct map_session_data *tsd); void clif_party_inviteack(struct map_session_data* sd, const char* nick, int flag); int clif_party_option(struct party_data *p,struct map_session_data *sd,int flag); int clif_party_withdraw(struct party_data* p, struct map_session_data* sd, int account_id, const char* name, int flag); @@ -515,7 +515,7 @@ void clif_get_weapon_view(struct map_session_data* sd, unsigned short *rhand, un int clif_party_xy_remove(struct map_session_data *sd); //Fix for minimap [Kevin] void clif_gospel_info(struct map_session_data *sd, int type); -void clif_parse_ReqFeel(int fd, struct map_session_data *sd, int skilllv); +void clif_feel_req(int fd, struct map_session_data *sd, int skilllv); void clif_starskill(struct map_session_data* sd, const char* mapname, int monster_id, unsigned char star, unsigned char result); void clif_feel_info(struct map_session_data *sd, unsigned char feel_level, unsigned char type); void clif_hate_info(struct map_session_data *sd, unsigned char hate_level,int class_, unsigned char type); diff --git a/src/map/guild.c b/src/map/guild.c index c80b124ef..0b77aa9a1 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -61,8 +61,8 @@ struct{ }need[6]; } guild_skill_tree[MAX_GUILDSKILL]; -int guild_payexp_timer(int tid, unsigned int tick, int id, intptr data); -static int guild_send_xy_timer(int tid, unsigned int tick, int id, intptr data); +int guild_payexp_timer(int tid, unsigned int tick, int id, intptr_t data); +static int guild_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data); /*========================================== * Retrieves and validates the sd pointer for this guild member [Skotlex] @@ -308,7 +308,7 @@ int guild_payexp_timer_sub(DBKey dataid, void *data, va_list ap) return 0; } -int guild_payexp_timer(int tid, unsigned int tick, int id, intptr data) +int guild_payexp_timer(int tid, unsigned int tick, int id, intptr_t data) { guild_expcache_db->clear(guild_expcache_db,guild_payexp_timer_sub); return 0; @@ -336,7 +336,7 @@ int guild_send_xy_timer_sub(DBKey key,void *data,va_list ap) } //Code from party_send_xy_timer [Skotlex] -static int guild_send_xy_timer(int tid, unsigned int tick, int id, intptr data) +static int guild_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data) { guild_db->foreach(guild_db,guild_send_xy_timer_sub,tick); return 0; @@ -1840,7 +1840,7 @@ int guild_castlealldataload(int len,struct guild_castle *gc) } // update mapserver castle data with new info - memcpy(&c->guild_id, &gc->guild_id, sizeof(struct guild_castle) - ((uintptr)&c->guild_id - (uintptr)c)); + memcpy(&c->guild_id, &gc->guild_id, sizeof(struct guild_castle) - ((uintptr_t)&c->guild_id - (uintptr_t)c)); if( c->guild_id ) { diff --git a/src/map/homunculus.c b/src/map/homunculus.c index 7bfb6081d..50b7c2c7a 100644 --- a/src/map/homunculus.c +++ b/src/map/homunculus.c @@ -45,7 +45,7 @@ struct s_homunculus_db homunculus_db[MAX_HOMUNCULUS_CLASS]; //[orn] struct skill_tree_entry hskill_tree[MAX_HOMUNCULUS_CLASS][MAX_SKILL_TREE]; -static int merc_hom_hungry(int tid, unsigned int tick, int id, intptr data); +static int merc_hom_hungry(int tid, unsigned int tick, int id, intptr_t data); static unsigned int hexptbl[MAX_LEVEL]; @@ -196,7 +196,7 @@ void merc_hom_skillup(struct homun_data *hd,int skillnum) i = skillnum - HM_SKILLBASE; if(hd->homunculus.skillpts > 0 && hd->homunculus.hskill[i].id && - hd->homunculus.hskill[i].flag == 0 && //Don't allow raising while you have granted skills. [Skotlex] + hd->homunculus.hskill[i].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex] hd->homunculus.hskill[i].lv < merc_skill_tree_get_max(skillnum, hd->homunculus.class_) ) { @@ -480,7 +480,7 @@ int merc_hom_food(struct map_session_data *sd, struct homun_data *hd) return 0; } -static int merc_hom_hungry(int tid, unsigned int tick, int id, intptr data) +static int merc_hom_hungry(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd; struct homun_data *hd; diff --git a/src/map/instance.c b/src/map/instance.c index e9ff2b409..d533a0188 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -28,6 +28,24 @@ int instance_start = 0; // To keep the last index + 1 of normal map inserted in the map[ARRAY] struct s_instance instance[MAX_INSTANCE]; + +/// Checks whether given instance id is valid or not. +static bool instance_is_valid(int instance_id) +{ + if( instance_id < 1 || instance_id >= ARRAYLENGTH(instance) ) + {// out of range + return false; + } + + if( instance[instance_id].state == INSTANCE_FREE ) + {// uninitialized/freed instance slot + return false; + } + + return true; +} + + /*-------------------------------------- * name : instance name * Return value could be @@ -62,13 +80,13 @@ int instance_create(int party_id, const char *name) instance[i].idle_timer = INVALID_TIMER; instance[i].idle_timeout = instance[i].idle_timeoutval = 0; instance[i].progress_timer = INVALID_TIMER; - instance[i].progress_timeout = instance[i].progress_timeoutval = 0; + instance[i].progress_timeout = 0; instance[i].users = 0; instance[i].party_id = party_id; instance[i].ivar = NULL; instance[i].svar = NULL; - memcpy( instance[i].name, name, sizeof(instance[i].name) ); + safestrncpy( instance[i].name, name, sizeof(instance[i].name) ); memset( instance[i].map, 0x00, sizeof(instance[i].map) ); p->instance_id = i; @@ -88,7 +106,7 @@ int instance_add_map(const char *name, int instance_id, bool usebasename) if( m < 0 ) return -1; // source map not found - if( instance[instance_id].state == INSTANCE_FREE ) + if( !instance_is_valid(instance_id) ) { ShowError("instance_add_map: trying to attach '%s' map to non-existing instance %d.\n", name, instance_id); return -1; @@ -158,6 +176,12 @@ int instance_add_map(const char *name, int instance_id, bool usebasename) int instance_map2imap(int m, int instance_id) { int i; + + if( !instance_is_valid(instance_id) ) + { + return -1; + } + for( i = 0; i < instance[instance_id].num_map; i++ ) { if( instance[instance_id].map[i] && map[instance[instance_id].map[i]].instance_src_map == m ) @@ -173,7 +197,6 @@ int instance_map2imap(int m, int instance_id) *--------------------------------------*/ int instance_mapid2imapid(int m, int instance_id) { - int i, max; if( map[m].flag.src4instance == 0 ) return m; // not instances found for this map else if( map[m].instance_id ) @@ -182,16 +205,10 @@ int instance_mapid2imapid(int m, int instance_id) return -1; } - if( instance_id <= 0 ) + if( !instance_is_valid(instance_id) ) return -1; - max = instance[instance_id].num_map; - - for( i = 0; i < max; i++ ) - if( map[instance[instance_id].map[i]].instance_src_map == m ) - return instance[instance_id].map[i]; - - return -1; + return instance_map2imap(m, instance_id); } /*-------------------------------------- @@ -214,13 +231,13 @@ void instance_init(int instance_id) { int i; - if( !instance_id ) + if( !instance_is_valid(instance_id) ) return; // nothing to do for( i = 0; i < instance[instance_id].num_map; i++ ) map_foreachinmap(instance_map_npcsub, map[instance[instance_id].map[i]].instance_src_map, BL_NPC, instance[instance_id].map[i]); - instance[instance_id].state = INSTANCE_BUSSY; + instance[instance_id].state = INSTANCE_BUSY; ShowInfo("[Instance] Initialized %s.\n", instance[instance_id].name); } @@ -294,7 +311,7 @@ void instance_destroy_freesvar(void *key, void *data, va_list args) /*-------------------------------------- * Timer to destroy instance by process or idle *--------------------------------------*/ -int instance_destroy_timer(int tid, unsigned int tick, int id, intptr data) +int instance_destroy_timer(int tid, unsigned int tick, int id, intptr_t data) { instance_destroy(id); return 0; @@ -309,7 +326,7 @@ void instance_destroy(int instance_id) struct party_data *p; time_t now = time(NULL); - if( !instance_id || instance[instance_id].state == INSTANCE_FREE ) + if( !instance_is_valid(instance_id) ) return; // nothing to do if( instance[instance_id].progress_timeout && instance[instance_id].progress_timeout <= now ) @@ -361,7 +378,7 @@ void instance_check_idle(int instance_id) bool idle = true; time_t now = time(NULL); - if( !instance_id || instance[instance_id].idle_timeoutval == 0 ) + if( !instance_is_valid(instance_id) || instance[instance_id].idle_timeoutval == 0 ) return; if( instance[instance_id].users ) @@ -389,7 +406,7 @@ void instance_set_timeout(int instance_id, unsigned int progress_timeout, unsign { time_t now = time(0); - if( !instance_id ) + if( !instance_is_valid(instance_id) ) return; if( instance[instance_id].progress_timer != INVALID_TIMER ) @@ -399,13 +416,11 @@ void instance_set_timeout(int instance_id, unsigned int progress_timeout, unsign if( progress_timeout ) { - instance[instance_id].progress_timeoutval = progress_timeout; instance[instance_id].progress_timeout = now + progress_timeout; instance[instance_id].progress_timer = add_timer( gettick() + progress_timeout * 1000, instance_destroy_timer, instance_id, 0); } else { - instance[instance_id].progress_timeoutval = 0; instance[instance_id].progress_timeout = 0; instance[instance_id].progress_timer = INVALID_TIMER; } @@ -444,6 +459,14 @@ void instance_check_kick(struct map_session_data *sd) } } +void do_final_instance(void) +{ + int i; + + for( i = 1; i < MAX_INSTANCE; i++ ) + instance_destroy(i); +} + void do_init_instance(void) { memset(instance, 0x00, sizeof(instance)); diff --git a/src/map/instance.h b/src/map/instance.h index c663503f5..e2b0354f9 100644 --- a/src/map/instance.h +++ b/src/map/instance.h @@ -7,10 +7,12 @@ #define MAX_MAP_PER_INSTANCE 10 #define MAX_INSTANCE 500 -typedef enum instance_state { INSTANCE_FREE, INSTANCE_IDLE, INSTANCE_BUSSY } instance_state; +#define INSTANCE_NAME_LENGTH (60+1) + +typedef enum instance_state { INSTANCE_FREE, INSTANCE_IDLE, INSTANCE_BUSY } instance_state; struct s_instance { - char name[61]; // Instance Name - required for clif functions. + char name[INSTANCE_NAME_LENGTH]; // Instance Name - required for clif functions. instance_state state; short instance_id; int party_id; @@ -22,7 +24,7 @@ struct s_instance { struct linkdb_node *ivar, *svar; // Instance Variable for scripts int progress_timer; - time_t progress_timeout, progress_timeoutval; + time_t progress_timeout; int idle_timer; time_t idle_timeout, idle_timeoutval; @@ -43,6 +45,7 @@ void instance_check_idle(int instance_id); void instance_check_kick(struct map_session_data *sd); void instance_set_timeout(int instance_id, unsigned int progress_timeout, unsigned int idle_timeout); -void do_init_instance(); +void do_final_instance(void); +void do_init_instance(void); #endif diff --git a/src/map/map.c b/src/map/map.c index c086b73c0..bc9465781 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -240,7 +240,7 @@ int map_freeblock_unlock (void) // この関数は、do_timer() のトップレベルから呼ばれるので、 // block_free_lock を直接いじっても支障無いはず。 -int map_freeblock_timer(int tid, unsigned int tick, int id, intptr data) +int map_freeblock_timer(int tid, unsigned int tick, int id, intptr_t data) { if (block_free_lock > 0) { ShowError("map_freeblock_timer: block_free_lock(%d) is invalid.\n", block_free_lock); @@ -1217,7 +1217,7 @@ int map_get_new_object_id(void) * 後者は、map_clearflooritem(id)へ * map.h?で#defineしてある *------------------------------------------*/ -int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr data) +int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr_t data) { struct flooritem_data* fitem = (struct flooritem_data*)idb_get(id_db, id); if( fitem==NULL || fitem->bl.type!=BL_ITEM || (!data && fitem->cleartimer != tid) ) @@ -2146,7 +2146,7 @@ int map_removemobs_sub(struct block_list *bl, va_list ap) return 1; } -int map_removemobs_timer(int tid, unsigned int tick, int id, intptr data) +int map_removemobs_timer(int tid, unsigned int tick, int id, intptr_t data) { int count; const int m = id; @@ -2727,7 +2727,7 @@ int map_readfromcache(struct map_data *m, char *buffer, char *decode_buffer) } // TO-DO: Maybe handle the scenario, if the decoded buffer isn't the same size as expected? [Shinryo] - uncompress(decode_buffer, &size, p+sizeof(struct map_cache_map_info), info->len); + decode_zip(decode_buffer, &size, p+sizeof(struct map_cache_map_info), info->len); CREATE(m->cell, struct mapcell, size); @@ -3436,9 +3436,6 @@ void do_final(void) for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) map_quit(sd); mapit_free(iter); - - for( i = 0; i < MAX_INSTANCE; i++ ) - instance_destroy(i); id_db->foreach(id_db,cleanup_db_sub); chrif_char_reset_offline(); @@ -3449,6 +3446,7 @@ void do_final(void) do_final_chrif(); do_final_npc(); do_final_script(); + do_final_instance(); do_final_itemdb(); do_final_storage(); do_final_guild(); @@ -3491,7 +3489,7 @@ void do_final(void) #ifndef TXT_ONLY map_sql_close(); #endif /* not TXT_ONLY */ - ShowStatus("Successfully terminated.\n"); + ShowStatus("Finished.\n"); } static int map_abort_sub(struct map_session_data* sd, va_list ap) @@ -3573,6 +3571,27 @@ void set_server_type(void) SERVER_TYPE = ATHENA_SERVER_MAP; } + +/// Called when a terminate signal is received. +void do_shutdown(void) +{ + if( runflag != MAPSERVER_ST_SHUTDOWN ) + { + runflag = MAPSERVER_ST_SHUTDOWN; + ShowStatus("Shutting down...\n"); + { + struct map_session_data* sd; + struct s_mapiterator* iter = mapit_getallusers(); + for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + clif_GM_kick(NULL, sd); + mapit_free(iter); + flush_fifos(); + } + chrif_check_shutdown(); + } +} + + int do_init(int argc, char *argv[]) { int i; @@ -3710,6 +3729,12 @@ int do_init(int argc, char *argv[]) ShowNotice("Server is running on '"CL_WHITE"PK Mode"CL_RESET"'.\n"); ShowStatus("Server is '"CL_GREEN"ready"CL_RESET"' and listening on port '"CL_WHITE"%d"CL_RESET"'.\n\n", map_port); + + if( runflag != CORE_ST_STOP ) + { + shutdown_callback = do_shutdown; + runflag = MAPSERVER_ST_RUNNING; + } return 0; } diff --git a/src/map/map.h b/src/map/map.h index d572cec4c..36496280e 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -4,9 +4,8 @@ #ifndef _MAP_H_ #define _MAP_H_ -#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" -#endif +#include "../common/core.h" // CORE_ST_LAST #include "../common/mmo.h" #include "../common/mapindex.h" #include "../common/db.h" @@ -16,6 +15,13 @@ struct npc_data; struct item_data; +enum E_MAPSERVER_ST +{ + MAPSERVER_ST_RUNNING = CORE_ST_LAST, + MAPSERVER_ST_SHUTDOWN, + MAPSERVER_ST_LAST +}; + //Uncomment to enable the Cell Stack Limit mod. //It's only config is the battle_config cell_stack_limit. //Only chars affected are those defined in BL_CHAR (mobs and players currently) @@ -615,8 +621,8 @@ int map_quit(struct map_session_data *); bool map_addnpc(int,struct npc_data *); // 床アイテム関連 -int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr data); -int map_removemobs_timer(int tid, unsigned int tick, int id, intptr data); +int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr_t data); +int map_removemobs_timer(int tid, unsigned int tick, int id, intptr_t data); #define map_clearflooritem(id) map_clearflooritem_timer(0,0,id,1) int map_addflooritem(struct item *item_data,int amount,int m,int x,int y,int first_charid,int second_charid,int third_charid,int flags); @@ -739,4 +745,6 @@ extern char mob_db2_db[32]; #endif /* not TXT_ONLY */ +void do_shutdown(void); + #endif /* _MAP_H_ */ diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c index f80be56a2..455da0f49 100644 --- a/src/map/mapreg_sql.c +++ b/src/map/mapreg_sql.c @@ -184,7 +184,7 @@ static void script_save_mapreg(void) mapreg_dirty = false; } -static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr data) +static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr_t data) { if( mapreg_dirty ) script_save_mapreg(); diff --git a/src/map/mapreg_txt.c b/src/map/mapreg_txt.c index 555b773ee..95be201e2 100644 --- a/src/map/mapreg_txt.c +++ b/src/map/mapreg_txt.c @@ -151,7 +151,7 @@ static void script_save_mapreg(void) mapreg_dirty = false; } -static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr data) +static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr_t data) { if( mapreg_dirty ) script_save_mapreg(); diff --git a/src/map/mercenary.c b/src/map/mercenary.c index 8300628d5..f6fa6bdaa 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -215,7 +215,7 @@ int mercenary_save(struct mercenary_data *md) return 1; } -static int merc_contract_end(int tid, unsigned int tick, int id, intptr data) +static int merc_contract_end(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd; struct mercenary_data *md; diff --git a/src/map/mob.c b/src/map/mob.c index 4c8fa685a..5fb440b4f 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -81,7 +81,7 @@ const int mob_splendide[5] = { 1991, 1992, 1993, 1994, 1995 }; * Local prototype declaration (only required thing) *------------------------------------------*/ static int mob_makedummymobdb(int); -static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr data); +static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr_t data); int mob_skillid2skillidx(int class_,int skillid); /*========================================== @@ -507,7 +507,7 @@ int mob_once_spawn_area(struct map_session_data* sd,int m,int x0,int y0,int x1,i /*========================================== * Set a Guardian's guild data [Skotlex] *------------------------------------------*/ -static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr data) +static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr_t data) { //Needed because the guild_data may not be available at guardian spawn time. struct block_list* bl = map_id2bl(id); struct mob_data* md; @@ -766,7 +766,7 @@ int mob_linksearch(struct block_list *bl,va_list ap) /*========================================== * mob spawn with delay (timer function) *------------------------------------------*/ -int mob_delayspawn(int tid, unsigned int tick, int id, intptr data) +int mob_delayspawn(int tid, unsigned int tick, int id, intptr_t data) { struct block_list* bl = map_id2bl(id); struct mob_data* md = BL_CAST(BL_MOB, bl); @@ -1636,7 +1636,7 @@ static int mob_ai_sub_lazy(struct mob_data *md, va_list args) /*========================================== * Negligent processing for mob outside PC field of view (interval timer function) *------------------------------------------*/ -static int mob_ai_lazy(int tid, unsigned int tick, int id, intptr data) +static int mob_ai_lazy(int tid, unsigned int tick, int id, intptr_t data) { map_foreachmob(mob_ai_sub_lazy,tick); return 0; @@ -1645,7 +1645,7 @@ static int mob_ai_lazy(int tid, unsigned int tick, int id, intptr data) /*========================================== * Serious processing for mob in PC field of view (interval timer function) *------------------------------------------*/ -static int mob_ai_hard(int tid, unsigned int tick, int id, intptr data) +static int mob_ai_hard(int tid, unsigned int tick, int id, intptr_t data) { if (battle_config.mob_ai&0x20) @@ -1684,7 +1684,7 @@ static struct item_drop* mob_setlootitem(struct item* item) /*========================================== * item drop with delay (timer function) *------------------------------------------*/ -static int mob_delay_item_drop(int tid, unsigned int tick, int id, intptr data) +static int mob_delay_item_drop(int tid, unsigned int tick, int id, intptr_t data) { struct item_drop_list *list; struct item_drop *ditem, *ditem_prev; @@ -1744,7 +1744,7 @@ static void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, str dlist->item = ditem; } -int mob_timer_delete(int tid, unsigned int tick, int id, intptr data) +int mob_timer_delete(int tid, unsigned int tick, int id, intptr_t data) { struct block_list* bl = map_id2bl(id); struct mob_data* md = BL_CAST(BL_MOB, bl); @@ -1791,7 +1791,7 @@ int mob_deleteslave(struct mob_data *md) return 0; } // Mob respawning through KAIZEL or NPC_REBIRTH [Skotlex] -int mob_respawn(int tid, unsigned int tick, int id, intptr data) +int mob_respawn(int tid, unsigned int tick, int id, intptr_t data) { struct block_list *bl = map_id2bl(id); @@ -2296,7 +2296,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) mob_item_drop(md, dlist, mob_setlootitem(&md->lootitem[i]), 1, 10000, homkillonly); } if (dlist->item) //There are drop items. - add_timer(tick + (!battle_config.delay_battle_damage?500:0), mob_delay_item_drop, 0, (intptr)dlist); + add_timer(tick + (!battle_config.delay_battle_damage?500:0), mob_delay_item_drop, 0, (intptr_t)dlist); else //No drops ers_free(item_drop_list_ers, dlist); } else if (md->lootitem && md->lootitem_count) { //Loot MUST drop! @@ -2310,7 +2310,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) dlist->item = NULL; for(i = 0; i < md->lootitem_count; i++) mob_item_drop(md, dlist, mob_setlootitem(&md->lootitem[i]), 1, 10000, homkillonly); - add_timer(tick + (!battle_config.delay_battle_damage?500:0), mob_delay_item_drop, 0, (intptr)dlist); + add_timer(tick + (!battle_config.delay_battle_damage?500:0), mob_delay_item_drop, 0, (intptr_t)dlist); } if(mvp_sd && md->db->mexp > 0 && !md->special_state.ai) @@ -3407,7 +3407,7 @@ static unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned shor *------------------------------------------*/ static bool mob_parse_dbrow(char** str) { - struct mob_db *db; + struct mob_db *db, entry; struct status_data *status; int class_, i, k; double exp, maxhp; @@ -3416,29 +3416,28 @@ static bool mob_parse_dbrow(char** str) class_ = atoi(str[0]); if (class_ <= 1000 || class_ > MAX_MOB_DB) { - ShowWarning("Mob with ID: %d not loaded. ID must be in range [%d-%d]\n", class_, 1000, MAX_MOB_DB); + ShowError("mob_parse_dbrow: Invalid monster ID %d, must be in range %d-%d.\n", class_, 1000, MAX_MOB_DB); return false; } if (pcdb_checkid(class_)) { - ShowWarning("Mob with ID: %d not loaded. That ID is reserved for player classes.\n", class_); + ShowError("mob_parse_dbrow: Invalid monster ID %d, reserved for player classes.\n", class_); return false; } if (class_ >= MOB_CLONE_START && class_ < MOB_CLONE_END) { - ShowWarning("Mob with ID: %d not loaded. Range %d-%d is reserved for player clones. Please increase MAX_MOB_DB (%d)\n", class_, MOB_CLONE_START, MOB_CLONE_END-1, MAX_MOB_DB); + ShowError("mob_parse_dbrow: Invalid monster ID %d. Range %d-%d is reserved for player clones. Please increase MAX_MOB_DB (%d).\n", class_, MOB_CLONE_START, MOB_CLONE_END-1, MAX_MOB_DB); return false; } - if (mob_db_data[class_] == NULL) - mob_db_data[class_] = (struct mob_db*)aCalloc(1, sizeof (struct mob_db)); + memset(&entry, 0, sizeof(entry)); - db = mob_db_data[class_]; + db = &entry; status = &db->status; db->vd.class_ = class_; - strncpy(db->sprite, str[1], NAME_LENGTH); - strncpy(db->jname, str[2], NAME_LENGTH); - strncpy(db->name, str[3], NAME_LENGTH); + safestrncpy(db->sprite, str[1], sizeof(db->sprite)); + safestrncpy(db->jname, str[2], sizeof(db->jname)); + safestrncpy(db->name, str[3], sizeof(db->name)); db->lv = atoi(str[4]); db->lv = cap_value(db->lv, 1, USHRT_MAX); status->max_hp = atoi(str[5]); @@ -3489,12 +3488,12 @@ static bool mob_parse_dbrow(char** str) status->def_ele = i%10; status->ele_lv = i/20; if (status->def_ele >= ELE_MAX) { - ShowWarning("Mob with ID: %d has invalid element type %d (max element is %d)\n", class_, status->def_ele, ELE_MAX-1); - status->def_ele = ELE_NEUTRAL; + ShowError("mob_parse_dbrow: Invalid element type %d for monster ID %d (max=%d).\n", status->def_ele, class_, ELE_MAX-1); + return false; } if (status->ele_lv < 1 || status->ele_lv > 4) { - ShowWarning("Mob with ID: %d has invalid element level %d (max is 4)\n", class_, status->ele_lv); - status->ele_lv = 1; + ShowError("mob_parse_dbrow: Invalid element level %d for monster ID %d, must be in range 1-4.\n", status->ele_lv, class_); + return false; } status->mode = (int)strtol(str[25], NULL, 0); @@ -3512,7 +3511,8 @@ static bool mob_parse_dbrow(char** str) status->dmotion = atoi(str[29]); if(battle_config.monster_damage_delay_rate != 100) status->dmotion = status->dmotion * battle_config.monster_damage_delay_rate / 100; - + + // Fill in remaining status data by using a dummy monster. data.bl.type = BL_MOB; data.level = db->lv; memcpy(&data.status, status, sizeof(struct status_data)); @@ -3632,7 +3632,12 @@ static bool mob_parse_dbrow(char** str) id->mob[k].id = class_; } } - + + // Finally insert monster's data into the database. + if (mob_db_data[class_] == NULL) + mob_db_data[class_] = (struct mob_db*)aCalloc(1, sizeof(struct mob_db)); + + memcpy(mob_db_data[class_], db, sizeof(struct mob_db)); return true; } diff --git a/src/map/mob.h b/src/map/mob.h index 605439f12..9e86b8d63 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -239,7 +239,7 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist); int mob_unlocktarget(struct mob_data *md, unsigned int tick); struct mob_data* mob_spawn_dataset(struct spawn_data *data); int mob_spawn(struct mob_data *md); -int mob_delayspawn(int tid, unsigned int tick, int id, intptr data); +int mob_delayspawn(int tid, unsigned int tick, int id, intptr_t data); int mob_setdelayspawn(struct mob_data *md); int mob_parse_dataset(struct spawn_data *data); void mob_log_damage(struct mob_data *md, struct block_list *src, int damage); @@ -256,7 +256,7 @@ void mob_clear_spawninfo(); int do_init_mob(void); int do_final_mob(void); -int mob_timer_delete(int tid, unsigned int tick, int id, intptr data); +int mob_timer_delete(int tid, unsigned int tick, int id, intptr_t data); int mob_deleteslave(struct mob_data *md); int mob_random_class (int *value, size_t count); diff --git a/src/map/npc.c b/src/map/npc.c index d070b6886..dd3a671b0 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -356,7 +356,7 @@ bool npc_event_isspecial(const char* eventname) /*========================================== * 時計イベント実行 *------------------------------------------*/ -int npc_event_do_clock(int tid, unsigned int tick, int id, intptr data) +int npc_event_do_clock(int tid, unsigned int tick, int id, intptr_t data) { static struct tm ev_tm_b; // tracks previous execution time time_t timer; @@ -455,7 +455,7 @@ struct timer_event_data { /*========================================== * triger 'OnTimerXXXX' events *------------------------------------------*/ -int npc_timerevent(int tid, unsigned int tick, int id, intptr data) +int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data) { int next; int old_rid, old_timer; @@ -498,9 +498,9 @@ int npc_timerevent(int tid, unsigned int tick, int id, intptr data) next = nd->u.scr.timer_event[ ted->next ].timer - nd->u.scr.timer_event[ ted->next - 1 ].timer; ted->time += next; if( sd ) - sd->npc_timer_id = add_timer(tick+next,npc_timerevent,id,(intptr)ted); + sd->npc_timer_id = add_timer(tick+next,npc_timerevent,id,(intptr_t)ted); else - nd->u.scr.timerid = add_timer(tick+next,npc_timerevent,id,(intptr)ted); + nd->u.scr.timerid = add_timer(tick+next,npc_timerevent,id,(intptr_t)ted); } else { @@ -570,13 +570,13 @@ int npc_timerevent_start(struct npc_data* nd, int rid) if( sd ) { ted->rid = sd->bl.id; // Attach only the player if attachplayerrid was used. - sd->npc_timer_id = add_timer(tick+next,npc_timerevent,nd->bl.id,(intptr)ted); + sd->npc_timer_id = add_timer(tick+next,npc_timerevent,nd->bl.id,(intptr_t)ted); } else { ted->rid = 0; nd->u.scr.timertick = tick; // Set when timer is started - nd->u.scr.timerid = add_timer(tick+next,npc_timerevent,nd->bl.id,(intptr)ted); + nd->u.scr.timerid = add_timer(tick+next,npc_timerevent,nd->bl.id,(intptr_t)ted); } return 0; @@ -1164,8 +1164,8 @@ static int npc_buylist_sub(struct map_session_data* sd, int n, unsigned short* i // save list of bought items for( i = 0; i < n; i++ ) { - script_setarray_pc(sd, "@bought_nameid", i, (void*)(intptr)item_list[i*2+1], &key_nameid); - script_setarray_pc(sd, "@bought_quantity", i, (void*)(intptr)item_list[i*2], &key_amount); + script_setarray_pc(sd, "@bought_nameid", i, (void*)(intptr_t)item_list[i*2+1], &key_nameid); + script_setarray_pc(sd, "@bought_quantity", i, (void*)(intptr_t)item_list[i*2], &key_amount); } // invoke event @@ -1369,8 +1369,9 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) // custom merchant shop exp bonus if( battle_config.shop_exp > 0 && z > 0 && (skill = pc_checkskill(sd,MC_DISCOUNT)) > 0 ) { - if( sd->status.skill[MC_DISCOUNT].flag != 0 ) - skill = sd->status.skill[MC_DISCOUNT].flag - 2; + if( sd->status.skill[MC_DISCOUNT].flag >= SKILL_FLAG_REPLACED_LV_0 ) + skill = sd->status.skill[MC_DISCOUNT].flag - SKILL_FLAG_REPLACED_LV_0; + if( skill > 0 ) { z = z * (double)skill * (double)battle_config.shop_exp/10000.; @@ -1401,8 +1402,8 @@ static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short* { idx = item_list[i*2]-2; - script_setarray_pc(sd, "@sold_nameid", i, (void*)(intptr)sd->status.inventory[idx].nameid, &key_nameid); - script_setarray_pc(sd, "@sold_quantity", i, (void*)(intptr)item_list[i*2+1], &key_amount); + script_setarray_pc(sd, "@sold_nameid", i, (void*)(intptr_t)sd->status.inventory[idx].nameid, &key_nameid); + script_setarray_pc(sd, "@sold_quantity", i, (void*)(intptr_t)item_list[i*2+1], &key_amount); } // invoke event @@ -1505,8 +1506,9 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list) // custom merchant shop exp bonus if( battle_config.shop_exp > 0 && z > 0 && ( skill = pc_checkskill(sd,MC_OVERCHARGE) ) > 0) { - if( sd->status.skill[MC_OVERCHARGE].flag != 0 ) - skill = sd->status.skill[MC_OVERCHARGE].flag - 2; + if( sd->status.skill[MC_OVERCHARGE].flag >= SKILL_FLAG_REPLACED_LV_0 ) + skill = sd->status.skill[MC_OVERCHARGE].flag - SKILL_FLAG_REPLACED_LV_0; + if( skill > 0 ) { z = z * (double)skill * (double)battle_config.shop_exp/10000.; @@ -2734,13 +2736,13 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c // check monster ID if exists! if( mobdb_checkid(class_) == 0 ) { - ShowError("npc_parse_mob: Unknown mob ID : %s %s (file '%s', line '%d').\n", w3, w4, filepath, strline(buffer,start-buffer)); + ShowError("npc_parse_mob: Unknown mob ID %d (file '%s', line '%d').\n", class_, filepath, strline(buffer,start-buffer)); return strchr(start,'\n');// skip and continue } if( num < 1 || num > 1000 ) { - ShowError("npc_parse_mob: Invalid number of monsters (must be inside the range [1,1000]) : %s %s (file '%s', line '%d').\n", w3, w4, filepath, strline(buffer,start-buffer)); + ShowError("npc_parse_mob: Invalid number of monsters %d, must be inside the range [1,1000] (file '%s', line '%d').\n", num, filepath, strline(buffer,start-buffer)); return strchr(start,'\n');// skip and continue } @@ -2786,7 +2788,7 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c } if(mob.delay1>0xfffffff || mob.delay2>0xfffffff) { - ShowError("npc_parse_mob: wrong monsters spawn delays : %s %s (file '%s', line '%d').\n", w3, w4, filepath, strline(buffer,start-buffer)); + ShowError("npc_parse_mob: Invalid spawn delays %u %u (file '%s', line '%d').\n", mob.delay1, mob.delay2, filepath, strline(buffer,start-buffer)); return strchr(start,'\n');// skip and continue } @@ -2801,7 +2803,7 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c //Verify dataset. if( !mob_parse_dataset(&mob) ) { - ShowError("npc_parse_mob: Invalid dataset : %s %s (file '%s', line '%d').\n", w3, w4, filepath, strline(buffer,start-buffer)); + ShowError("npc_parse_mob: Invalid dataset for monster ID %d (file '%s', line '%d').\n", class_, filepath, strline(buffer,start-buffer)); return strchr(start,'\n');// skip and continue } diff --git a/src/map/npc.h b/src/map/npc.h index 6e7c7cbeb..29e3d79cb 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -77,7 +77,7 @@ struct npc_data { #define MAX_NPC_CLASS 1000 //Checks if a given id is a valid npc id. [Skotlex] //Since new npcs are added all the time, the max valid value is the one before the first mob (Scorpion = 1001) -#define npcdb_checkid(id) ((id >= 46 && id <= 125) || id == 139 || (id >= 400 && id <= MAX_NPC_CLASS) || id == INVISIBLE_CLASS) +#define npcdb_checkid(id) ( ( (id) >= 46 && (id) <= 125) || (id) == 139 || ( (id) > 400 && (id) < MAX_NPC_CLASS ) || (id) == INVISIBLE_CLASS ) #ifdef PCRE_SUPPORT void npc_chat_finalize(struct npc_data* nd); diff --git a/src/map/party.c b/src/map/party.c index 47dba49e9..88f53bcb0 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -32,7 +32,7 @@ static DBMap* party_db; // int party_id -> struct party_data* static DBMap* party_booking_db; // Party Booking [Spiria] static unsigned long party_booking_nextid = 1; -int party_send_xy_timer(int tid, unsigned int tick, int id, intptr data); +int party_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data); /*========================================== * Fills the given party_member structure according to the sd provided. @@ -369,11 +369,19 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd) return 1; } -void party_reply_invite(struct map_session_data *sd,int account_id,int flag) +void party_reply_invite(struct map_session_data *sd,int party_id,int flag) { - struct map_session_data *tsd= map_id2sd(account_id); + struct map_session_data* tsd; struct party_member member; + if( sd->party_invite != party_id ) + {// forged + sd->party_invite = 0; + sd->party_invite_account = 0; + return; + } + tsd = map_id2sd(sd->party_invite_account); + if( flag == 1 && !sd->party_creating && !sd->party_joining ) {// accepted and allowed sd->party_joining = true; @@ -832,7 +840,7 @@ int party_skill_check(struct map_session_data *sd, int party_id, int skillid, in return 0; } -int party_send_xy_timer(int tid, unsigned int tick, int id, intptr data) +int party_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data) { struct party_data* p; diff --git a/src/map/party.h b/src/map/party.h index 31e46f5ec..1c59197b3 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -62,7 +62,7 @@ int party_member_added(int party_id,int account_id,int char_id,int flag); int party_leave(struct map_session_data *sd); int party_removemember(struct map_session_data *sd,int account_id,char *name); int party_member_withdraw(int party_id,int account_id,int char_id); -void party_reply_invite(struct map_session_data *sd,int account_id,int flag); +void party_reply_invite(struct map_session_data *sd,int party_id,int flag); int party_recv_noinfo(int party_id); int party_recv_info(struct party *sp); int party_recv_movemap(int party_id,int account_id,int char_id, unsigned short map,int online,int lv); diff --git a/src/map/pc.c b/src/map/pc.c index 6d4002599..a9d798ade 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -85,7 +85,7 @@ int pc_isGM(struct map_session_data* sd) return sd->gmlevel; } -static int pc_invincible_timer(int tid, unsigned int tick, int id, intptr data) +static int pc_invincible_timer(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd; @@ -123,7 +123,7 @@ void pc_delinvincibletimer(struct map_session_data* sd) } } -static int pc_spiritball_timer(int tid, unsigned int tick, int id, intptr data) +static int pc_spiritball_timer(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd; int i; @@ -295,7 +295,7 @@ int pc_setrestartvalue(struct map_session_data *sd,int type) /*========================================== Rental System *------------------------------------------*/ -static int pc_inventory_rental_end(int tid, unsigned int tick, int id, intptr data) +static int pc_inventory_rental_end(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd = map_id2sd(id); if( sd == NULL ) @@ -695,7 +695,7 @@ bool pc_can_Adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd return false; } - if( !(b_sd->status.class_ >= JOB_NOVICE && b_sd->status.class_ <= JOB_THIEF) ) + if( !( ( b_sd->status.class_ >= JOB_NOVICE && b_sd->status.class_ <= JOB_THIEF ) || b_sd->status.class_ == JOB_SUPER_NOVICE ) ) return false; return true; @@ -1061,9 +1061,9 @@ int pc_reg_received(struct map_session_data *sd) if (sd->cloneskill_id > 0) { sd->status.skill[sd->cloneskill_id].id = sd->cloneskill_id; sd->status.skill[sd->cloneskill_id].lv = pc_readglobalreg(sd,"CLONE_SKILL_LV"); - if (i < sd->status.skill[sd->cloneskill_id].lv) + if (sd->status.skill[sd->cloneskill_id].lv > i) sd->status.skill[sd->cloneskill_id].lv = i; - sd->status.skill[sd->cloneskill_id].flag = 13; //cloneskill flag + sd->status.skill[sd->cloneskill_id].flag = SKILL_FLAG_PLAGIARIZED; } } @@ -1124,11 +1124,11 @@ static int pc_calc_skillpoint(struct map_session_data* sd) if((!(inf2&INF2_QUEST_SKILL) || battle_config.quest_skill_learn) && !(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) //Do not count wedding/link skills. [Skotlex] ) { - if(!sd->status.skill[i].flag) + if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) skill_point += skill; - else if(sd->status.skill[i].flag > 2 && sd->status.skill[i].flag != 13) { - skill_point += (sd->status.skill[i].flag - 2); - } + else + if(sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0) + skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0); } } } @@ -1157,16 +1157,16 @@ int pc_calc_skilltree(struct map_session_data *sd) for( i = 0; i < MAX_SKILL; i++ ) { - if( sd->status.skill[i].flag != 13 ) //Don't touch plagiarized skills + if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED ) //Don't touch plagiarized skills sd->status.skill[i].id = 0; //First clear skills. } for( i = 0; i < MAX_SKILL; i++ ) { - if( sd->status.skill[i].flag && sd->status.skill[i].flag != 13 ) + if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED ) { // Restore original level of skills after deleting earned skills. - sd->status.skill[i].lv = (sd->status.skill[i].flag == 1)?0:sd->status.skill[i].flag-2; - sd->status.skill[i].flag = 0; + sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0; + sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; } if( sd->sc.count && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_BARDDANCER && i >= DC_HUMMING && i<= DC_SERVICEFORYOU ) @@ -1177,7 +1177,7 @@ int pc_calc_skilltree(struct map_session_data *sd) continue; sd->status.skill[i].id = i; sd->status.skill[i].lv = sd->status.skill[i-8].lv; // Set the level to the same as the linking skill - sd->status.skill[i].flag = 1; // Tag it as a non-savable, non-uppable, bonus skill + sd->status.skill[i].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill } else { //Link bard skills to dancer. @@ -1185,7 +1185,7 @@ int pc_calc_skilltree(struct map_session_data *sd) continue; sd->status.skill[i-8].id = i - 8; sd->status.skill[i-8].lv = sd->status.skill[i].lv; // Set the level to the same as the linking skill - sd->status.skill[i-8].flag = 1; // Tag it as a non-savable, non-uppable, bonus skill + sd->status.skill[i-8].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill } } } @@ -1216,10 +1216,11 @@ int pc_calc_skilltree(struct map_session_data *sd) for(j = 0; j < MAX_PC_SKILL_REQUIRE; j++) { if((k=skill_tree[c][i].need[j].id)) { - if (!sd->status.skill[k].id || sd->status.skill[k].flag == 13) + if (sd->status.skill[k].id == 0 || sd->status.skill[k].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[k].flag == SKILL_FLAG_PLAGIARIZED) k = 0; //Not learned. - else if (sd->status.skill[k].flag) //Real lerned level - k = sd->status.skill[skill_tree[c][i].need[j].id].flag-2; + else + if (sd->status.skill[k].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level + k = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0; else k = pc_checkskill(sd,k); if (k < skill_tree[c][i].need[j].lv) @@ -1249,7 +1250,7 @@ int pc_calc_skilltree(struct map_session_data *sd) if(inf2&INF2_SPIRIT_SKILL) { //Spirit skills cannot be learned, they will only show up on your tree when you get buffed. sd->status.skill[id].lv = 1; // need to manually specify a skill level - sd->status.skill[id].flag = 1; //So it is not saved, and tagged as a "bonus" skill. + sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill. } flag = 1; // skill list has changed, perform another pass } @@ -1273,10 +1274,12 @@ int pc_calc_skilltree(struct map_session_data *sd) if( sd->status.skill[id].id == 0 ) { sd->status.skill[id].id = id; - sd->status.skill[id].flag = 1; // So it is not saved, and tagged as a "bonus" skill. + sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; // So it is not saved, and tagged as a "bonus" skill. } else - sd->status.skill[id].flag = sd->status.skill[id].lv+2; + { + sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Remember original level + } sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class_); } @@ -1314,10 +1317,11 @@ static void pc_check_skilltree(struct map_session_data *sd, int skill) { if( (k = skill_tree[c][i].need[j].id) ) { - if( !sd->status.skill[k].id || sd->status.skill[k].flag == 13 ) + if( sd->status.skill[k].id == 0 || sd->status.skill[k].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[k].flag == SKILL_FLAG_PLAGIARIZED ) k = 0; //Not learned. - else if( sd->status.skill[k].flag ) //Real lerned level - k = sd->status.skill[skill_tree[c][i].need[j].id].flag - 2; + else + if( sd->status.skill[k].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level + k = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0; else k = pc_checkskill(sd,k); if( k < skill_tree[c][i].need[j].lv ) @@ -1352,13 +1356,15 @@ int pc_clean_skilltree(struct map_session_data *sd) { int i; for (i = 0; i < MAX_SKILL; i++){ - if (sd->status.skill[i].flag == 13 || sd->status.skill[i].flag == 1) + if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED) { sd->status.skill[i].id = 0; sd->status.skill[i].lv = 0; sd->status.skill[i].flag = 0; - } else if (sd->status.skill[i].flag){ - sd->status.skill[i].lv = sd->status.skill[i].flag-2; + } + else + if (sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0){ + sd->status.skill[i].lv = sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0; sd->status.skill[i].flag = 0; } } @@ -1716,14 +1722,14 @@ int pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *autobonus) script_run_autobonus(autobonus->other_script,sd->bl.id,sd->equip_index[j]); } - autobonus->active = add_timer(gettick()+autobonus->duration, pc_endautobonus, sd->bl.id, (intptr)autobonus); + autobonus->active = add_timer(gettick()+autobonus->duration, pc_endautobonus, sd->bl.id, (intptr_t)autobonus); sd->state.autobonus |= autobonus->pos; status_calc_pc(sd,0); return 0; } -int pc_endautobonus(int tid, unsigned int tick, int id, intptr data) +int pc_endautobonus(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd = map_id2sd(id); struct s_autobonus *autobonus = (struct s_autobonus *)data; @@ -2321,8 +2327,8 @@ int pc_bonus(struct map_session_data *sd,int type,int val) sd->right_weapon.hp_drain[RC_BOSS].value += val; } else if(sd->state.lr_flag == 1) { - sd->right_weapon.hp_drain[RC_NONBOSS].value += val; - sd->right_weapon.hp_drain[RC_BOSS].value += val; + sd->left_weapon.hp_drain[RC_NONBOSS].value += val; + sd->left_weapon.hp_drain[RC_BOSS].value += val; } break; case SP_SP_DRAIN_VALUE: @@ -3060,8 +3066,8 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) case 0: //Set skill data overwriting whatever was there before. sd->status.skill[id].id = id; sd->status.skill[id].lv = level; - sd->status.skill[id].flag = 0; - if( !level ) //Remove skill. + sd->status.skill[id].flag = SKILL_FLAG_PERMANENT; + if( level == 0 ) //Remove skill. { sd->status.skill[id].id = 0; clif_deleteskill(sd,id); @@ -3075,21 +3081,21 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) if( sd->status.skill[id].id == id ){ if( sd->status.skill[id].lv >= level ) return 0; - if( !sd->status.skill[id].flag ) //Non-granted skill, store it's level. - sd->status.skill[id].flag = sd->status.skill[id].lv + 2; + if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) //Non-granted skill, store it's level. + sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; } else { sd->status.skill[id].id = id; - sd->status.skill[id].flag = 1; + sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; } sd->status.skill[id].lv = level; break; case 2: //Add skill bonus on top of what you had. if( sd->status.skill[id].id == id ){ - if( !sd->status.skill[id].flag ) // Store previous level. - sd->status.skill[id].flag = sd->status.skill[id].lv + 2; + if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) + sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Store previous level. } else { sd->status.skill[id].id = id; - sd->status.skill[id].flag = 1; //Set that this is a bonus skill. + sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; //Set that this is a bonus skill. } sd->status.skill[id].lv += level; break; @@ -4789,7 +4795,8 @@ const char* job_name(int class_) case JOB_WEDDING: case JOB_SUPER_NOVICE: - + case JOB_GUNSLINGER: + case JOB_NINJA: case JOB_XMAS: return msg_txt(570 - JOB_WEDDING+class_); @@ -4870,11 +4877,6 @@ const char* job_name(int class_) return msg_txt(617); case JOB_SOUL_LINKER: return msg_txt(618); - - case JOB_GUNSLINGER: - return msg_txt(619); - case JOB_NINJA: - return msg_txt(620); case JOB_RUNE_KNIGHT: case JOB_WARLOCK: @@ -4958,7 +4960,7 @@ const char* job_name(int class_) } } -int pc_follow_timer(int tid, unsigned int tick, int id, intptr data) +int pc_follow_timer(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd; struct block_list *tbl; @@ -5507,7 +5509,7 @@ int pc_skillup(struct map_session_data *sd,int skill_num) if( sd->status.skill_point > 0 && sd->status.skill[skill_num].id && - sd->status.skill[skill_num].flag == 0 && //Don't allow raising while you have granted skills. [Skotlex] + sd->status.skill[skill_num].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex] sd->status.skill[skill_num].lv < skill_tree_get_max(skill_num, sd->status.class_) ) { sd->status.skill[skill_num].lv++; @@ -5537,11 +5539,11 @@ int pc_allskillup(struct map_session_data *sd) nullpo_ret(sd); for(i=0;i<MAX_SKILL;i++){ - if (sd->status.skill[i].flag && sd->status.skill[i].flag != 13){ - sd->status.skill[i].lv=(sd->status.skill[i].flag==1)?0:sd->status.skill[i].flag-2; - sd->status.skill[i].flag=0; - if (!sd->status.skill[i].lv) - sd->status.skill[i].id=0; + if (sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) { + sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0; + sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; + if (sd->status.skill[i].lv == 0) + sd->status.skill[i].id = 0; } } @@ -5771,7 +5773,7 @@ int pc_resetskill(struct map_session_data* sd, int flag) if( i == NV_BASIC && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE && (sd->class_&MAPID_UPPERMASK) != MAPID_BABY ) { // Official server does not include Basic Skill to be resetted. [Jobbie] sd->status.skill[i].lv = 9; - sd->status.skill[i].flag = 0; + sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; continue; } @@ -5784,13 +5786,14 @@ int pc_resetskill(struct map_session_data* sd, int flag) } continue; } - if( !sd->status.skill[i].flag ) + if( sd->status.skill[i].flag == SKILL_FLAG_PERMANENT ) skill_point += lv; - else if( sd->status.skill[i].flag > 2 && sd->status.skill[i].flag != 13 ) - skill_point += (sd->status.skill[i].flag - 2); + else + if( sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0 ) + skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0); if( !(flag&2) ) - { + {// reset sd->status.skill[i].lv = 0; sd->status.skill[i].flag = 0; } @@ -5896,7 +5899,7 @@ void pc_respawn(struct map_session_data* sd, clr_type clrtype) clif_resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet. } -static int pc_respawn_timer(int tid, unsigned int tick, int id, intptr data) +static int pc_respawn_timer(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd = map_id2sd(id); if( sd != NULL ) @@ -6602,6 +6605,12 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) } if(sd->cloneskill_id) { + if( sd->status.skill[sd->cloneskill_id].flag == SKILL_FLAG_PLAGIARIZED ) { + sd->status.skill[sd->cloneskill_id].id = 0; + sd->status.skill[sd->cloneskill_id].lv = 0; + sd->status.skill[sd->cloneskill_id].flag = 0; + clif_deleteskill(sd,sd->cloneskill_id); + } sd->cloneskill_id = 0; pc_setglobalreg(sd, "CLONE_SKILL", 0); pc_setglobalreg(sd, "CLONE_SKILL_LV", 0); @@ -7261,7 +7270,7 @@ int pc_setregistry_str(struct map_session_data *sd,const char *reg,const char *v /*========================================== * イベントタイマ??理 *------------------------------------------*/ -static int pc_eventtimer(int tid, unsigned int tick, int id, intptr data) +static int pc_eventtimer(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd=map_id2sd(id); char *p = (char *)data; @@ -7295,7 +7304,7 @@ int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name) if( i == MAX_EVENTTIMER ) return 0; - sd->eventtimer[i] = add_timer(gettick()+tick, pc_eventtimer, sd->bl.id, (intptr)aStrdup(name)); + sd->eventtimer[i] = add_timer(gettick()+tick, pc_eventtimer, sd->bl.id, (intptr_t)aStrdup(name)); sd->eventcount++; return 1; @@ -7761,7 +7770,7 @@ int pc_calc_pvprank(struct map_session_data *sd) /*========================================== * PVP順位計算(timer) *------------------------------------------*/ -int pc_calc_pvprank_timer(int tid, unsigned int tick, int id, intptr data) +int pc_calc_pvprank_timer(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd=NULL; @@ -7960,7 +7969,7 @@ int pc_setsavepoint(struct map_session_data *sd, short mapindex,int x,int y) /*========================================== * 自動セ?ブ (timer??) *------------------------------------------*/ -int pc_autosave(int tid, unsigned int tick, int id, intptr data) +int pc_autosave(int tid, unsigned int tick, int id, intptr_t data) { int interval; struct s_mapiterator* iter; @@ -8014,7 +8023,7 @@ static int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap) * timer to do the day [Yor] * data: 0 = called by timer, 1 = gmcommand/script *------------------------------------------------*/ -int map_day_timer(int tid, unsigned int tick, int id, intptr data) +int map_day_timer(int tid, unsigned int tick, int id, intptr_t data) { char tmp_soutput[1024]; @@ -8035,7 +8044,7 @@ int map_day_timer(int tid, unsigned int tick, int id, intptr data) * timer to do the night [Yor] * data: 0 = called by timer, 1 = gmcommand/script *------------------------------------------------*/ -int map_night_timer(int tid, unsigned int tick, int id, intptr data) +int map_night_timer(int tid, unsigned int tick, int id, intptr_t data) { char tmp_soutput[1024]; diff --git a/src/map/pc.h b/src/map/pc.h index 271b3f6b0..fdf4094a1 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -582,8 +582,8 @@ int pc_calc_skilltree(struct map_session_data *sd); int pc_calc_skilltree_normalize_job(struct map_session_data *sd); int pc_clean_skilltree(struct map_session_data *sd); -#define pc_checkoverhp(sd) (sd->battle_status.hp == sd->battle_status.max_hp) -#define pc_checkoversp(sd) (sd->battle_status.sp == sd->battle_status.max_sp) +#define pc_checkoverhp(sd) ((sd)->battle_status.hp == (sd)->battle_status.max_hp) +#define pc_checkoversp(sd) ((sd)->battle_status.sp == (sd)->battle_status.max_sp) int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y, clr_type clrtype); int pc_setsavepoint(struct map_session_data*,short,int,int); @@ -621,7 +621,7 @@ int pc_updateweightstatus(struct map_session_data *sd); int pc_addautobonus(struct s_autobonus *bonus,char max,const char *script,short rate,unsigned int dur,short atk_type,const char *o_script,unsigned short pos,bool onskill); int pc_exeautobonus(struct map_session_data* sd,struct s_autobonus *bonus); -int pc_endautobonus(int tid, unsigned int tick, int id, intptr data); +int pc_endautobonus(int tid, unsigned int tick, int id, intptr_t data); int pc_delautobonus(struct map_session_data* sd,struct s_autobonus *bonus,char max,bool restore); int pc_bonus(struct map_session_data*,int,int); @@ -715,7 +715,7 @@ int pc_cleareventtimer(struct map_session_data *sd); int pc_addeventtimercount(struct map_session_data *sd,const char *name,int tick); int pc_calc_pvprank(struct map_session_data *sd); -int pc_calc_pvprank_timer(int tid, unsigned int tick, int id, intptr data); +int pc_calc_pvprank_timer(int tid, unsigned int tick, int id, intptr_t data); int pc_ismarried(struct map_session_data *sd); int pc_marriage(struct map_session_data *sd,struct map_session_data *dstsd); @@ -779,8 +779,8 @@ enum {ADDITEM_EXIST,ADDITEM_NEW,ADDITEM_OVERAMOUNT}; // timer for night.day extern int day_timer_tid; extern int night_timer_tid; -int map_day_timer(int tid, unsigned int tick, int id, intptr data); // by [yor] -int map_night_timer(int tid, unsigned int tick, int id, intptr data); // by [yor] +int map_day_timer(int tid, unsigned int tick, int id, intptr_t data); // by [yor] +int map_night_timer(int tid, unsigned int tick, int id, intptr_t data); // by [yor] // Rental System void pc_inventory_rentals(struct map_session_data *sd); diff --git a/src/map/pet.c b/src/map/pet.c index 1f350ec4b..a0f652f2b 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -189,7 +189,7 @@ int pet_sc_check(struct map_session_data *sd, int type) return 0; } -static int pet_hungry(int tid, unsigned int tick, int id, intptr data) +static int pet_hungry(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd; struct pet_data *pd; @@ -858,6 +858,7 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns if (pd->ud.walktimer != INVALID_TIMER) return 0; //Wait until the pet finishes walking back to master. pd->status.speed = pd->petDB->speed; + pd->ud.state.change_walk_target = pd->ud.state.speed_changed = 1; } if (pd->target_id) { @@ -934,7 +935,7 @@ static int pet_ai_sub_foreachclient(struct map_session_data *sd,va_list ap) return 0; } -static int pet_ai_hard(int tid, unsigned int tick, int id, intptr data) +static int pet_ai_hard(int tid, unsigned int tick, int id, intptr_t data) { map_foreachpc(pet_ai_sub_foreachclient,tick); @@ -968,7 +969,7 @@ static int pet_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap) return 0; } -static int pet_delay_item_drop(int tid, unsigned int tick, int id, intptr data) +static int pet_delay_item_drop(int tid, unsigned int tick, int id, intptr_t data) { struct item_drop_list *list; struct item_drop *ditem, *ditem_prev; @@ -1029,7 +1030,7 @@ int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd) pd->ud.canact_tick = gettick()+10000; // 10*1000msの間拾わない if (dlist->item) - add_timer(gettick()+540,pet_delay_item_drop,0,(intptr)dlist); + add_timer(gettick()+540,pet_delay_item_drop,0,(intptr_t)dlist); else ers_free(item_drop_list_ers, dlist); return 1; @@ -1038,7 +1039,7 @@ int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd) /*========================================== * pet bonus giving skills [Valaris] / Rewritten by [Skotlex] *------------------------------------------*/ -int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr data) +int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd=map_id2sd(id); struct pet_data *pd; @@ -1080,7 +1081,7 @@ int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr data) /*========================================== * pet recovery skills [Valaris] / Rewritten by [Skotlex] *------------------------------------------*/ -int pet_recovery_timer(int tid, unsigned int tick, int id, intptr data) +int pet_recovery_timer(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd=map_id2sd(id); struct pet_data *pd; @@ -1108,7 +1109,7 @@ int pet_recovery_timer(int tid, unsigned int tick, int id, intptr data) return 0; } -int pet_heal_timer(int tid, unsigned int tick, int id, intptr data) +int pet_heal_timer(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd=map_id2sd(id); struct status_data *status; @@ -1146,7 +1147,7 @@ int pet_heal_timer(int tid, unsigned int tick, int id, intptr data) /*========================================== * pet support skills [Skotlex] *------------------------------------------*/ -int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr data) +int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd=map_id2sd(id); struct pet_data *pd; diff --git a/src/map/pet.h b/src/map/pet.h index 729fdeb92..52f4999df 100644 --- a/src/map/pet.h +++ b/src/map/pet.h @@ -121,10 +121,10 @@ int pet_change_name_ack(struct map_session_data *sd, char* name, int flag); int pet_equipitem(struct map_session_data *sd,int index); int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd); int pet_attackskill(struct pet_data *pd, int target_id); -int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr data); // [Skotlex] -int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr data); // [Valaris] -int pet_recovery_timer(int tid, unsigned int tick, int id, intptr data); // [Valaris] -int pet_heal_timer(int tid, unsigned int tick, int id, intptr data); // [Valaris] +int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr_t data); // [Skotlex] +int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr_t data); // [Valaris] +int pet_recovery_timer(int tid, unsigned int tick, int id, intptr_t data); // [Valaris] +int pet_heal_timer(int tid, unsigned int tick, int id, intptr_t data); // [Valaris] #define pet_stop_walking(pd, type) unit_stop_walking(&(pd)->bl, type) #define pet_stop_attack(pd) unit_stop_attack(&(pd)->bl) diff --git a/src/map/quest.c b/src/map/quest.c index 4960d8a93..4c890ce9e 100644 --- a/src/map/quest.c +++ b/src/map/quest.c @@ -85,7 +85,7 @@ int quest_add(TBL_PC * sd, int quest_id) i = sd->avail_quests; memmove(&sd->quest_log[i+1], &sd->quest_log[i], sizeof(struct quest)*(sd->num_quests-sd->avail_quests)); - memmove(sd->quest_index+i+1, sd->quest_log+i, sizeof(int)*(sd->num_quests-sd->avail_quests)); + memmove(sd->quest_index+i+1, sd->quest_index+i, sizeof(int)*(sd->num_quests-sd->avail_quests)); memset(&sd->quest_log[i], 0, sizeof(struct quest)); sd->quest_log[i].quest_id = quest_db[j].id; diff --git a/src/map/script.c b/src/map/script.c index bf0b4f652..632dc0e14 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -246,9 +246,13 @@ enum curly_type { TYPE_ARGLIST // function argument list }; -#define ARGLIST_UNDEFINED 0 -#define ARGLIST_NO_PAREN 1 -#define ARGLIST_PAREN 2 +enum e_arglist +{ + ARGLIST_UNDEFINED = 0, + ARGLIST_NO_PAREN = 1, + ARGLIST_PAREN = 2, +}; + static struct { struct { enum curly_type type; @@ -3315,7 +3319,7 @@ struct linkdb_node* script_erase_sleepdb(struct linkdb_node *n) /*========================================== * sleep用タイマー関数 *------------------------------------------*/ -int run_script_timer(int tid, unsigned int tick, int id, intptr data) +int run_script_timer(int tid, unsigned int tick, int id, intptr_t data) { struct script_state *st = (struct script_state *)data; struct linkdb_node *node = (struct linkdb_node *)sleep_db; @@ -3512,7 +3516,7 @@ void run_script_main(struct script_state *st) sd = map_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 = add_timer(gettick()+st->sleep.tick, - run_script_timer, st->sleep.charid, (intptr)st); + run_script_timer, st->sleep.charid, (intptr_t)st); linkdb_insert(&sleep_db, (void*)st->oid, st); } else if(st->state != END && st->rid){ @@ -4550,7 +4554,7 @@ BUILDIN_FUNC(warpchar) *------------------------------------------*/ BUILDIN_FUNC(warpparty) { - TBL_PC *sd; + TBL_PC *sd = NULL; TBL_PC *pl_sd; struct party_data* p; int type; @@ -4565,22 +4569,21 @@ BUILDIN_FUNC(warpparty) if ( script_hasdata(st,6) ) str2 = script_getstr(st,6); - sd=script_rid2sd(st); - if( sd == NULL ) - return 0; p = party_search(p_id); if(!p) return 0; - if(map[sd->bl.m].flag.noreturn || map[sd->bl.m].flag.nowarpto) - return 0; - type = ( strcmp(str,"Random")==0 ) ? 0 : ( strcmp(str,"SavePointAll")==0 ) ? 1 : ( strcmp(str,"SavePoint")==0 ) ? 2 : ( strcmp(str,"Leader")==0 ) ? 3 : 4; + if( type == 2 && ( sd = script_rid2sd(st) ) == NULL ) + {// "SavePoint" uses save point of the currently attached player + return 0; + } + for (i = 0; i < MAX_PARTY; i++) { if( !(pl_sd = p->data[i].sd) || pl_sd->status.party_id != p_id ) @@ -4638,7 +4641,7 @@ BUILDIN_FUNC(warpparty) *------------------------------------------*/ BUILDIN_FUNC(warpguild) { - TBL_PC *sd; + TBL_PC *sd = NULL; TBL_PC *pl_sd; struct guild* g; struct s_mapiterator* iter; @@ -4649,21 +4652,20 @@ BUILDIN_FUNC(warpguild) int y = script_getnum(st,4); int gid = script_getnum(st,5); - sd=script_rid2sd(st); - if( sd == NULL ) - return 0; g = guild_search(gid); if( g == NULL ) return 0; - if(map[sd->bl.m].flag.noreturn || map[sd->bl.m].flag.nowarpto) - return 0; - type = ( strcmp(str,"Random")==0 ) ? 0 : ( strcmp(str,"SavePointAll")==0 ) ? 1 : ( strcmp(str,"SavePoint")==0 ) ? 2 : 3; + if( type == 2 && ( sd = script_rid2sd(st) ) == NULL ) + {// "SavePoint" uses save point of the currently attached player + return 0; + } + iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) { @@ -11682,6 +11684,62 @@ BUILDIN_FUNC(gethominfo) return 0; } +/// Retrieves information about character's mercenary +/// getmercinfo <type>[,<char id>]; +BUILDIN_FUNC(getmercinfo) +{ + int type, char_id; + struct map_session_data* sd; + struct mercenary_data* md; + + type = script_getnum(st,2); + + if( script_hasdata(st,3) ) + { + char_id = script_getnum(st,3); + + if( ( sd = map_charid2sd(char_id) ) == NULL ) + { + ShowError("buildin_getmercinfo: No such character (char_id=%d).\n", char_id); + script_pushnil(st); + return 1; + } + } + else + { + if( ( sd = script_rid2sd(st) ) == NULL ) + { + script_pushnil(st); + return 0; + } + } + + md = ( sd->status.mer_id && sd->md ) ? sd->md : NULL; + + switch( type ) + { + case 0: script_pushint(st,md ? md->mercenary.mercenary_id : 0); break; + case 1: script_pushint(st,md ? md->mercenary.class_ : 0); break; + case 2: + if( md ) + script_pushstrcopy(st,md->db->name); + else + script_pushconststr(st,""); + break; + case 3: script_pushint(st,md ? mercenary_get_faith(md) : 0); break; + case 4: script_pushint(st,md ? mercenary_get_calls(md) : 0); break; + case 5: script_pushint(st,md ? md->mercenary.kill_count : 0); break; + case 6: script_pushint(st,md ? mercenary_get_lifetime(md) : 0); break; + case 7: script_pushint(st,md ? md->db->lv : 0); break; + default: + ShowError("buildin_getmercinfo: Invalid type %d (char_id=%d).\n", type, sd->status.char_id); + script_pushnil(st); + return 1; + } + + return 0; +} + /*========================================== * Shows wether your inventory(and equips) contain selected card or not. @@ -11788,7 +11846,7 @@ BUILDIN_FUNC(movenpc) return -1; if (script_hasdata(st,5)) - nd->ud.dir = script_getnum(st,5); + nd->ud.dir = script_getnum(st,5) % 8; npc_movenpc(nd, x, y); return 0; } @@ -12871,7 +12929,7 @@ BUILDIN_FUNC(npcshopitem) int n, i; int amount; - if( !nd || nd->subtype != SHOP ) + if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) ) { //Not found. script_pushint(st,0); return 0; @@ -12900,7 +12958,7 @@ BUILDIN_FUNC(npcshopadditem) int n, i; int amount; - if( !nd || nd->subtype != SHOP ) + if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) ) { //Not found. script_pushint(st,0); return 0; @@ -12931,7 +12989,7 @@ BUILDIN_FUNC(npcshopdelitem) int amount; int size; - if( !nd || nd->subtype != SHOP ) + if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) ) { //Not found. script_pushint(st,0); return 0; @@ -15141,6 +15199,7 @@ struct script_function buildin_func[] = { BUILDIN_DEF(recovery,""), BUILDIN_DEF(getpetinfo,"i"), BUILDIN_DEF(gethominfo,"i"), + BUILDIN_DEF(getmercinfo,"i?"), BUILDIN_DEF(checkequipedcard,"i"), BUILDIN_DEF(jump_zero,"il"), //for future jA script compatibility BUILDIN_DEF(globalmes,"s?"), diff --git a/src/map/script.h b/src/map/script.h index c272f2d32..2ed163a0f 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -153,7 +153,7 @@ void run_script(struct script_code*,int,int,int); int set_var(struct map_session_data *sd, char *name, void *val); int conv_num(struct script_state *st,struct script_data *data); const char* conv_str(struct script_state *st,struct script_data *data); -int run_script_timer(int tid, unsigned int tick, int id, intptr data); +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_sleeptimers(int id); diff --git a/src/map/skill.c b/src/map/skill.c index d95d04134..d33d35d6e 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -43,11 +43,11 @@ // ranges reserved for mapping skill ids to skilldb offsets #define GD_SKILLRANGEMIN 900 -#define GD_SKILLRANGEMAX GD_SKILLRANGEMIN+MAX_GUILDSKILL +#define GD_SKILLRANGEMAX (GD_SKILLRANGEMIN+MAX_GUILDSKILL) #define MC_SKILLRANGEMIN 800 -#define MC_SKILLRANGEMAX MC_SKILLRANGEMIN+MAX_MERCSKILL +#define MC_SKILLRANGEMAX (MC_SKILLRANGEMIN+MAX_MERCSKILL) #define HM_SKILLRANGEMIN 700 -#define HM_SKILLRANGEMAX HM_SKILLRANGEMIN+MAX_HOMUNSKILL +#define HM_SKILLRANGEMAX (HM_SKILLRANGEMIN+MAX_HOMUNSKILL) static struct eri *skill_unit_ers = NULL; //For handling skill_unit's [Skotlex] static struct eri *skill_timer_ers = NULL; //For handling skill_timerskills [Skotlex] @@ -1820,11 +1820,11 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds && (!sc || !sc->data[SC_PRESERVE]) && damage < tsd->battle_status.hp) { //Updated to not be able to copy skills if the blow will kill you. [Skotlex] - if ((!tsd->status.skill[skillid].id || tsd->status.skill[skillid].flag >= 13) && + if ((tsd->status.skill[skillid].id == 0 || tsd->status.skill[skillid].flag == SKILL_FLAG_PLAGIARIZED) && can_copy(tsd,skillid,bl)) // Split all the check into their own function [Aru] { int lv = skilllv; - if (tsd->cloneskill_id && tsd->status.skill[tsd->cloneskill_id].flag == 13){ + if (tsd->cloneskill_id && tsd->status.skill[tsd->cloneskill_id].flag == SKILL_FLAG_PLAGIARIZED){ tsd->status.skill[tsd->cloneskill_id].id = 0; tsd->status.skill[tsd->cloneskill_id].lv = 0; tsd->status.skill[tsd->cloneskill_id].flag = 0; @@ -1840,7 +1840,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds tsd->status.skill[skillid].id = skillid; tsd->status.skill[skillid].lv = lv; - tsd->status.skill[skillid].flag = 13;//cloneskill flag + tsd->status.skill[skillid].flag = SKILL_FLAG_PLAGIARIZED; clif_addskill(tsd,skillid); } } @@ -2277,7 +2277,7 @@ int skill_area_sub_count (struct block_list *src, struct block_list *target, int /*========================================== * *------------------------------------------*/ -static int skill_timerskill(int tid, unsigned int tick, int id, intptr data) +static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) { struct block_list *src = map_id2bl(id),*target; struct unit_data *ud = unit_bl2ud(src); @@ -3958,51 +3958,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case KN_BRANDISHSPEAR: case ML_BRANDISH: - { - int c,n=4; - int dir = map_calc_dir(src,bl->x,bl->y); - struct square tc; - int x=bl->x,y=bl->y; - skill_brandishspear_first(&tc,dir,x,y); - skill_brandishspear_dir(&tc,dir,4); - skill_area_temp[1] = bl->id; - - if(skilllv > 9){ - for(c=1;c<4;c++){ - map_foreachincell(skill_area_sub, - bl->m,tc.val1[c],tc.val2[c],BL_CHAR, - src,skillid,skilllv,tick, flag|BCT_ENEMY|n, - skill_castend_damage_id); - } - } - if(skilllv > 6){ - skill_brandishspear_dir(&tc,dir,-1); - n--; - }else{ - skill_brandishspear_dir(&tc,dir,-2); - n-=2; - } - - if(skilllv > 3){ - for(c=0;c<5;c++){ - map_foreachincell(skill_area_sub, - bl->m,tc.val1[c],tc.val2[c],BL_CHAR, - src,skillid,skilllv,tick, flag|BCT_ENEMY|n, - skill_castend_damage_id); - if(skilllv > 6 && n==3 && c==4){ - skill_brandishspear_dir(&tc,dir,-1); - n--;c=-1; - } - } - } - for(c=0;c<10;c++){ - if(c==0||c==5) skill_brandishspear_dir(&tc,dir,-1); - map_foreachincell(skill_area_sub, - bl->m,tc.val1[c%5],tc.val2[c%5],BL_CHAR, - src,skillid,skilllv,tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); - } - } + skill_brandishspear(src, bl, skillid, skilllv, tick, flag); break; case WZ_SIGHTRASHER: @@ -5531,7 +5487,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in //AuronX reported you CAN memorize the same map as all three. [Skotlex] if (sd) { if(!sd->feel_map[skilllv-1].index) - clif_parse_ReqFeel(sd->fd,sd, skilllv); + clif_feel_req(sd->fd,sd, skilllv); else clif_feel_info(sd, skilllv-1, 1); } @@ -5726,7 +5682,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in /*========================================== * *------------------------------------------*/ -int skill_castend_id(int tid, unsigned int tick, int id, intptr data) +int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) { struct block_list *target, *src; struct map_session_data *sd; @@ -6016,7 +5972,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr data) /*========================================== * *------------------------------------------*/ -int skill_castend_pos(int tid, unsigned int tick, int id, intptr data) +int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data) { struct block_list* src = map_id2bl(id); int maxcount; @@ -9149,7 +9105,12 @@ int skill_delayfix (struct block_list *bl, int skill_id, int skill_lv) /*========================================= * *-----------------------------------------*/ -void skill_brandishspear_first (struct square *tc, int dir, int x, int y) +struct square { + int val1[5]; + int val2[5]; +}; + +static void skill_brandishspear_first (struct square *tc, int dir, int x, int y) { nullpo_retv(tc); @@ -9252,10 +9213,7 @@ void skill_brandishspear_first (struct square *tc, int dir, int x, int y) } -/*========================================= - * - *-----------------------------------------*/ -void skill_brandishspear_dir (struct square* tc, int dir, int are) +static void skill_brandishspear_dir (struct square* tc, int dir, int are) { int c; nullpo_retv(tc); @@ -9276,6 +9234,53 @@ void skill_brandishspear_dir (struct square* tc, int dir, int are) } } +void skill_brandishspear(struct block_list* src, struct block_list* bl, int skillid, int skilllv, unsigned int tick, int flag) +{ + int c,n=4; + int dir = map_calc_dir(src,bl->x,bl->y); + struct square tc; + int x=bl->x,y=bl->y; + skill_brandishspear_first(&tc,dir,x,y); + skill_brandishspear_dir(&tc,dir,4); + skill_area_temp[1] = bl->id; + + if(skilllv > 9){ + for(c=1;c<4;c++){ + map_foreachincell(skill_area_sub, + bl->m,tc.val1[c],tc.val2[c],BL_CHAR, + src,skillid,skilllv,tick, flag|BCT_ENEMY|n, + skill_castend_damage_id); + } + } + if(skilllv > 6){ + skill_brandishspear_dir(&tc,dir,-1); + n--; + }else{ + skill_brandishspear_dir(&tc,dir,-2); + n-=2; + } + + if(skilllv > 3){ + for(c=0;c<5;c++){ + map_foreachincell(skill_area_sub, + bl->m,tc.val1[c],tc.val2[c],BL_CHAR, + src,skillid,skilllv,tick, flag|BCT_ENEMY|n, + skill_castend_damage_id); + if(skilllv > 6 && n==3 && c==4){ + skill_brandishspear_dir(&tc,dir,-1); + n--;c=-1; + } + } + } + for(c=0;c<10;c++){ + if(c==0||c==5) skill_brandishspear_dir(&tc,dir,-1); + map_foreachincell(skill_area_sub, + bl->m,tc.val1[c%5],tc.val2[c%5],BL_CHAR, + src,skillid,skilllv,tick, flag|BCT_ENEMY|1, + skill_castend_damage_id); + } +} + /*========================================== * Weapon Repair [Celest/DracoRPG] *------------------------------------------*/ @@ -10485,7 +10490,7 @@ static int skill_unit_timer_sub (DBKey key, void* data, va_list ap) /*========================================== * Executes on all skill units every SKILLUNITTIMER_INTERVAL miliseconds. *------------------------------------------*/ -int skill_unit_timer(int tid, unsigned int tick, int id, intptr data) +int skill_unit_timer(int tid, unsigned int tick, int id, intptr_t data) { map_freeblock_lock(); @@ -11181,7 +11186,7 @@ int skill_arrow_create (struct map_session_data *sd, int nameid) /*========================================== * *------------------------------------------*/ -int skill_blockpc_end(int tid, unsigned int tick, int id, intptr data) +int skill_blockpc_end(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd = map_id2sd(id); if (data <= 0 || data >= MAX_SKILL) @@ -11212,7 +11217,7 @@ int skill_blockpc_start(struct map_session_data *sd, int skillid, int tick) return 0; } -int skill_blockhomun_end(int tid, unsigned int tick, int id, intptr data) //[orn] +int skill_blockhomun_end(int tid, unsigned int tick, int id, intptr_t data) //[orn] { struct homun_data *hd = (TBL_HOM*) map_id2bl(id); if (data <= 0 || data >= MAX_SKILL) @@ -11238,7 +11243,7 @@ int skill_blockhomun_start(struct homun_data *hd, int skillid, int tick) //[orn] return add_timer(gettick() + tick, skill_blockhomun_end, hd->bl.id, skillid); } -int skill_blockmerc_end(int tid, unsigned int tick, int id, intptr data) //[orn] +int skill_blockmerc_end(int tid, unsigned int tick, int id, intptr_t data) //[orn] { struct mercenary_data *md = (TBL_MER*)map_id2bl(id); if( data <= 0 || data >= MAX_SKILL ) diff --git a/src/map/skill.h b/src/map/skill.h index 6f55af7ec..1ad6ea25a 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -22,51 +22,61 @@ struct status_change_entry; #define MAX_SKILL_LEVEL 100 //Constants to identify the skill's inf value: -#define INF_ATTACK_SKILL 1 -#define INF_GROUND_SKILL 2 -// Skills casted on self where target is automatically chosen: -#define INF_SELF_SKILL 4 -#define INF_SUPPORT_SKILL 16 -#define INF_TARGET_TRAP 32 +enum e_skill_inf +{ + INF_ATTACK_SKILL = 0x01, + INF_GROUND_SKILL = 0x02, + INF_SELF_SKILL = 0x04, // Skills casted on self where target is automatically chosen + // 0x08 not assigned + INF_SUPPORT_SKILL = 0x10, + INF_TARGET_TRAP = 0x20, +}; //Constants to identify a skill's nk value (damage properties) //The NK value applies only to non INF_GROUND_SKILL skills //when determining skill castend function to invoke. -#define NK_NO_DAMAGE 0x01 -#define NK_SPLASH (0x02|0x04) // 0x4 = splash & split -#define NK_SPLASHSPLIT 0x04 -#define NK_NO_CARDFIX_ATK 0x08 -#define NK_NO_ELEFIX 0x10 -#define NK_IGNORE_DEF 0x20 -#define NK_IGNORE_FLEE 0x40 -#define NK_NO_CARDFIX_DEF 0x80 +enum e_skill_nk +{ + NK_NO_DAMAGE = 0x01, + NK_SPLASH = 0x02|0x04, // 0x4 = splash & split + NK_SPLASHSPLIT = 0x04, + NK_NO_CARDFIX_ATK = 0x08, + NK_NO_ELEFIX = 0x10, + NK_IGNORE_DEF = 0x20, + NK_IGNORE_FLEE = 0x40, + NK_NO_CARDFIX_DEF = 0x80, +}; //A skill with 3 would be no damage + splash: area of effect. //Constants to identify a skill's inf2 value. -#define INF2_QUEST_SKILL 1 -//NPC skills are those that players can't have in their skill tree. -#define INF2_NPC_SKILL 0x2 -#define INF2_WEDDING_SKILL 0x4 -#define INF2_SPIRIT_SKILL 0x8 -#define INF2_GUILD_SKILL 0x10 -#define INF2_SONG_DANCE 0x20 -#define INF2_ENSEMBLE_SKILL 0x40 -#define INF2_TRAP 0x80 -//Refers to ground placed skills that will target the caster as well (like Grandcross) -#define INF2_TARGET_SELF 0x100 -#define INF2_NO_TARGET_SELF 0x200 -#define INF2_PARTY_ONLY 0x400 -#define INF2_GUILD_ONLY 0x800 -#define INF2_NO_ENEMY 0x1000 +enum e_skill_inf2 +{ + INF2_QUEST_SKILL = 0x0001, + INF2_NPC_SKILL = 0x0002, //NPC skills are those that players can't have in their skill tree. + INF2_WEDDING_SKILL = 0x0004, + INF2_SPIRIT_SKILL = 0x0008, + INF2_GUILD_SKILL = 0x0010, + INF2_SONG_DANCE = 0x0020, + INF2_ENSEMBLE_SKILL = 0x0040, + INF2_TRAP = 0x0080, + INF2_TARGET_SELF = 0x0100, //Refers to ground placed skills that will target the caster as well (like Grandcross) + INF2_NO_TARGET_SELF = 0x0200, + INF2_PARTY_ONLY = 0x0400, + INF2_GUILD_ONLY = 0x0800, + INF2_NO_ENEMY = 0x1000, +}; //Walk intervals at which chase-skills are attempted to be triggered. #define WALK_SKILL_INTERVAL 5 // Flags passed to skill_attack/skill_area_sub -#define SD_LEVEL 0x1000 // skill_attack will send -1 instead of skill level (affects display of some skills) -#define SD_ANIMATION 0x2000 // skill_attack will use '5' instead of the skill's 'type' (this makes skills show an animation) -#define SD_SPLASH 0x4000 // skill_area_sub will count targets in skill_area_temp[2] -#define SD_PREAMBLE 0x8000 // skill_area_sub will transmit a 'magic' damage packet (-30000 dmg) for the first target selected +enum e_skill_display +{ + SD_LEVEL = 0x1000, // skill_attack will send -1 instead of skill level (affects display of some skills) + SD_ANIMATION = 0x2000, // skill_attack will use '5' instead of the skill's 'type' (this makes skills show an animation) + SD_SPLASH = 0x4000, // skill_area_sub will count targets in skill_area_temp[2] + SD_PREAMBLE = 0x8000, // skill_area_sub will transmit a 'magic' damage packet (-30000 dmg) for the first target selected +}; #define MAX_SKILL_ITEM_REQUIRE 10 struct skill_condition { @@ -253,8 +263,8 @@ const char* skill_get_desc( int id ); // [Skotlex] int skill_name2id(const char* name); int skill_isammotype(struct map_session_data *sd, int skill); -int skill_castend_id(int tid, unsigned int tick, int id, intptr data); -int skill_castend_pos(int tid, unsigned int tick, int id, intptr data); +int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data); +int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data); int skill_castend_map( struct map_session_data *sd,short skill_num, const char *map); int skill_cleartimerskill(struct block_list *src); @@ -305,8 +315,7 @@ int skill_guildaura_sub (struct block_list *bl,va_list ap); int skill_castcancel(struct block_list *bl,int type); int skill_sit (struct map_session_data *sd, int type); -void skill_brandishspear_first(struct square *tc,int dir,int x,int y); -void skill_brandishspear_dir(struct square *tc,int dir,int are); +void skill_brandishspear(struct block_list* src, struct block_list* bl, int skillid, int skilllv, unsigned int tick, int flag); void skill_repairweapon(struct map_session_data *sd, int idx); void skill_identify(struct map_session_data *sd,int idx); void skill_weaponrefine(struct map_session_data *sd,int idx); // [Celest] diff --git a/src/map/sql/CMakeLists.txt b/src/map/sql/CMakeLists.txt new file mode 100644 index 000000000..74598423a --- /dev/null +++ b/src/map/sql/CMakeLists.txt @@ -0,0 +1,110 @@ + +# +# map sql +# +if( HAVE_common_sql ) +message( STATUS "Creating target map-server_sql" ) +set( SQL_MAP_HEADERS + "${MAP_SOURCE_DIR}/atcommand.h" + "${MAP_SOURCE_DIR}/battle.h" + "${MAP_SOURCE_DIR}/battleground.h" + "${MAP_SOURCE_DIR}/buyingstore.h" + "${MAP_SOURCE_DIR}/chat.h" + "${MAP_SOURCE_DIR}/chrif.h" + "${MAP_SOURCE_DIR}/clif.h" + "${MAP_SOURCE_DIR}/date.h" + "${MAP_SOURCE_DIR}/duel.h" + "${MAP_SOURCE_DIR}/guild.h" + "${MAP_SOURCE_DIR}/homunculus.h" + "${MAP_SOURCE_DIR}/instance.h" + "${MAP_SOURCE_DIR}/intif.h" + "${MAP_SOURCE_DIR}/itemdb.h" + "${MAP_SOURCE_DIR}/log.h" + "${MAP_SOURCE_DIR}/mail.h" + "${MAP_SOURCE_DIR}/map.h" + "${MAP_SOURCE_DIR}/mapreg.h" + "${MAP_SOURCE_DIR}/mercenary.h" + "${MAP_SOURCE_DIR}/mob.h" + "${MAP_SOURCE_DIR}/npc.h" + "${MAP_SOURCE_DIR}/party.h" + "${MAP_SOURCE_DIR}/path.h" + "${MAP_SOURCE_DIR}/pc.h" + "${MAP_SOURCE_DIR}/pet.h" + "${MAP_SOURCE_DIR}/quest.h" + "${MAP_SOURCE_DIR}/script.h" + "${MAP_SOURCE_DIR}/searchstore.h" + "${MAP_SOURCE_DIR}/skill.h" + "${MAP_SOURCE_DIR}/status.h" + "${MAP_SOURCE_DIR}/storage.h" + "${MAP_SOURCE_DIR}/trade.h" + "${MAP_SOURCE_DIR}/unit.h" + "${MAP_SOURCE_DIR}/vending.h" + ) +set( SQL_MAP_SOURCES + "${MAP_SOURCE_DIR}/atcommand.c" + "${MAP_SOURCE_DIR}/battle.c" + "${MAP_SOURCE_DIR}/battleground.c" + "${MAP_SOURCE_DIR}/buyingstore.c" + "${MAP_SOURCE_DIR}/chat.c" + "${MAP_SOURCE_DIR}/chrif.c" + "${MAP_SOURCE_DIR}/clif.c" + "${MAP_SOURCE_DIR}/date.c" + "${MAP_SOURCE_DIR}/duel.c" + "${MAP_SOURCE_DIR}/guild.c" + "${MAP_SOURCE_DIR}/homunculus.c" + "${MAP_SOURCE_DIR}/instance.c" + "${MAP_SOURCE_DIR}/intif.c" + "${MAP_SOURCE_DIR}/itemdb.c" + "${MAP_SOURCE_DIR}/log.c" + "${MAP_SOURCE_DIR}/mail.c" + "${MAP_SOURCE_DIR}/map.c" + "${MAP_SOURCE_DIR}/mapreg_sql.c" + "${MAP_SOURCE_DIR}/mercenary.c" + "${MAP_SOURCE_DIR}/mob.c" + "${MAP_SOURCE_DIR}/npc.c" + "${MAP_SOURCE_DIR}/npc_chat.c" + "${MAP_SOURCE_DIR}/party.c" + "${MAP_SOURCE_DIR}/path.c" + "${MAP_SOURCE_DIR}/pc.c" + "${MAP_SOURCE_DIR}/pet.c" + "${MAP_SOURCE_DIR}/quest.c" + "${MAP_SOURCE_DIR}/script.c" + "${MAP_SOURCE_DIR}/searchstore.c" + "${MAP_SOURCE_DIR}/skill.c" + "${MAP_SOURCE_DIR}/status.c" + "${MAP_SOURCE_DIR}/storage.c" + "${MAP_SOURCE_DIR}/trade.c" + "${MAP_SOURCE_DIR}/unit.c" + "${MAP_SOURCE_DIR}/vending.c" + ) +set( DEPENDENCIES common_sql ) +set( LIBRARIES ${GLOBAL_LIBRARIES} ) +set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ) +set( DEFINITIONS ${GLOBAL_DEFINITIONS} ) +if( WITH_PCRE ) + message( STATUS "Using PCRE" ) + list( APPEND LIBRARIES ${PCRE_LIBRARIES} ) + list( APPEND INCLUDE_DIRS ${PCRE_INCLUDE_DIRS} ) + list( APPEND DEFINITIONS PCRE_SUPPORT ) +endif() +set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ${SQL_MAP_HEADERS} ${SQL_MAP_SOURCES} ) +source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ) +source_group( map FILES ${SQL_MAP_HEADERS} ${SQL_MAP_SOURCES} ) +include_directories( ${INCLUDE_DIRS} ) +add_executable( map-server_sql ${SOURCE_FILES} ) +add_dependencies( map-server_sql ${DEPENDENCIES} ) +target_link_libraries( map-server_sql ${LIBRARIES} ${DEPENDENCIES} ) +set_target_properties( map-server_sql PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" ) +if( WITH_COMPONENT_RUNTIME ) + cpack_add_component( Runtime_mapserver_sql DESCRIPTION "map-server (sql version)" DISPLAY_NAME "map-server_sql" GROUP Runtime ) + install( TARGETS map-server_sql + DESTINATION "." + COMPONENT Runtime_mapserver_sql ) +endif() +message( STATUS "Creating target map-server_sql - done" ) +set( HAVE_map-server_sql ON CACHE BOOL "map-server_sql target is available" ) +mark_as_advanced( HAVE_map-server_sql ) +else() +message( STATUS "Skipping target map-server_sql (requires common_sql; optional PCRE)" ) +unset( HAVE_map-server_sql CACHE ) +endif() diff --git a/src/map/status.c b/src/map/status.c index e68ebd291..37dad30b9 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -38,10 +38,13 @@ //Regen related flags. -#define RGN_HP 0x01 -#define RGN_SP 0x02 -#define RGN_SHP 0x04 -#define RGN_SSP 0x08 +enum e_regen +{ + RGN_HP = 0x01, + RGN_SP = 0x02, + RGN_SHP = 0x04, + RGN_SSP = 0x08, +}; static int max_weight_base[CLASS_COUNT]; static int hp_coefficient[CLASS_COUNT]; @@ -6961,7 +6964,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const return 1; } -int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr data) +int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr_t data) { struct block_list *bl; struct status_change *sc; @@ -6998,7 +7001,7 @@ int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr data) /*========================================== * ステータス異常終了タイマー *------------------------------------------*/ -int status_change_timer(int tid, unsigned int tick, int id, intptr data) +int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) { enum sc_type type = (sc_type)data; struct block_list *bl; @@ -7258,7 +7261,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr data) case SC_BERSERK: // 5% every 10 seconds [DracoRPG] - if(--(sce->val3)>0 && status_charge(bl, sce->val2, 0)) + if( --( sce->val3 ) > 0 && status_charge(bl, sce->val2, 0) && status->hp > 100 ) { sc_timer_next(sce->val4+tick, status_change_timer, bl->id, data); return 0; @@ -7689,7 +7692,7 @@ static int status_natural_heal(struct block_list* bl, va_list args) } //Natural heal main timer. -static int status_natural_heal_timer(int tid, unsigned int tick, int id, intptr data) +static int status_natural_heal_timer(int tid, unsigned int tick, int id, intptr_t data) { natural_heal_diff_tick = DIFF_TICK(tick,natural_heal_prev_tick); map_foreachregen(status_natural_heal); diff --git a/src/map/status.h b/src/map/status.h index 45eaa5c8d..abaeff75e 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -915,13 +915,16 @@ enum si_type { }; // JOINTBEAT stackable ailments -#define BREAK_ANKLE 0x01 // MoveSpeed reduced by 50% -#define BREAK_WRIST 0x02 // ASPD reduced by 25% -#define BREAK_KNEE 0x04 // MoveSpeed reduced by 30%, ASPD reduced by 10% -#define BREAK_SHOULDER 0x08 // DEF reduced by 50% -#define BREAK_WAIST 0x10 // DEF reduced by 25%, ATK reduced by 25% -#define BREAK_NECK 0x20 // current attack does 2x damage, inflicts 'bleeding' for 30 seconds -#define BREAK_FLAGS ( BREAK_ANKLE | BREAK_WRIST | BREAK_KNEE | BREAK_SHOULDER | BREAK_WAIST | BREAK_NECK ) +enum e_joint_break +{ + BREAK_ANKLE = 0x01, // MoveSpeed reduced by 50% + BREAK_WRIST = 0x02, // ASPD reduced by 25% + BREAK_KNEE = 0x04, // MoveSpeed reduced by 30%, ASPD reduced by 10% + BREAK_SHOULDER = 0x08, // DEF reduced by 50% + BREAK_WAIST = 0x10, // DEF reduced by 25%, ATK reduced by 25% + BREAK_NECK = 0x20, // current attack does 2x damage, inflicts 'bleeding' for 30 seconds + BREAK_FLAGS = BREAK_ANKLE | BREAK_WRIST | BREAK_KNEE | BREAK_SHOULDER | BREAK_WAIST | BREAK_NECK, +}; extern int current_equip_item_index; extern int current_equip_card_id; @@ -929,22 +932,25 @@ extern int current_equip_card_id; extern int percentrefinery[5][MAX_REFINE+1]; //The last slot always has a 0% success chance [Skotlex] //Mode definitions to clear up code reading. [Skotlex] -#define MD_CANMOVE 0x0001 -#define MD_LOOTER 0x0002 -#define MD_AGGRESSIVE 0x0004 -#define MD_ASSIST 0x0008 -#define MD_CASTSENSOR_IDLE 0x0010 -#define MD_BOSS 0x0020 -#define MD_PLANT 0x0040 -#define MD_CANATTACK 0x0080 -#define MD_DETECTOR 0x0100 -#define MD_CASTSENSOR_CHASE 0x0200 -#define MD_CHANGECHASE 0x0400 -#define MD_ANGRY 0x0800 -#define MD_CHANGETARGET_MELEE 0x1000 -#define MD_CHANGETARGET_CHASE 0x2000 -#define MD_TARGETWEAK 0x4000 -#define MD_MASK 0xFFFF +enum e_mode +{ + MD_CANMOVE = 0x0001, + MD_LOOTER = 0x0002, + MD_AGGRESSIVE = 0x0004, + MD_ASSIST = 0x0008, + MD_CASTSENSOR_IDLE = 0x0010, + MD_BOSS = 0x0020, + MD_PLANT = 0x0040, + MD_CANATTACK = 0x0080, + MD_DETECTOR = 0x0100, + MD_CASTSENSOR_CHASE = 0x0200, + MD_CHANGECHASE = 0x0400, + MD_ANGRY = 0x0800, + MD_CHANGETARGET_MELEE = 0x1000, + MD_CHANGETARGET_CHASE = 0x2000, + MD_TARGETWEAK = 0x4000, + MD_MASK = 0xFFFF, +}; //Status change option definitions (options are what makes status changes visible to chars //who were not on your field of sight when it happened) @@ -1026,19 +1032,21 @@ enum { OPTION_DRAGON3 = 0x01000000, OPTION_DRAGON4 = 0x02000000, OPTION_DRAGON5 = 0x04000000, + // compound constants + OPTION_CART = OPTION_CART1|OPTION_CART2|OPTION_CART3|OPTION_CART4|OPTION_CART5, + OPTION_DRAGON = OPTION_DRAGON1|OPTION_DRAGON2|OPTION_DRAGON3|OPTION_DRAGON4|OPTION_DRAGON5, + OPTION_MASK = ~OPTION_INVISIBLE, }; -#define OPTION_CART (OPTION_CART1|OPTION_CART2|OPTION_CART3|OPTION_CART4|OPTION_CART5) -#define OPTION_DRAGON (OPTION_DRAGON1|OPTION_DRAGON2|OPTION_DRAGON3|OPTION_DRAGON4|OPTION_DRAGON5) - -#define OPTION_MASK ~0x40 - //Defines for the manner system [Skotlex] -#define MANNER_NOCHAT 0x01 -#define MANNER_NOSKILL 0x02 -#define MANNER_NOCOMMAND 0x04 -#define MANNER_NOITEM 0x08 -#define MANNER_NOROOM 0x10 +enum manner_flags +{ + MANNER_NOCHAT = 0x01, + MANNER_NOSKILL = 0x02, + MANNER_NOCOMMAND = 0x04, + MANNER_NOITEM = 0x08, + MANNER_NOROOM = 0x10, +}; //Define flags for the status_calc_bl function. [Skotlex] enum scb_flag @@ -1278,8 +1286,8 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,int flag); int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const char* file, int line); #define status_change_end(bl,type,tid) status_change_end_(bl,type,tid,__FILE__,__LINE__) -int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr data); -int status_change_timer(int tid, unsigned int tick, int id, intptr data); +int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr_t data); +int status_change_timer(int tid, unsigned int tick, int id, intptr_t data); int status_change_timer_sub(struct block_list* bl, va_list ap); int status_change_clear(struct block_list* bl, int type); int status_change_clear_buffs(struct block_list* bl, int type); diff --git a/src/map/txt/CMakeLists.txt b/src/map/txt/CMakeLists.txt new file mode 100644 index 000000000..d58866f96 --- /dev/null +++ b/src/map/txt/CMakeLists.txt @@ -0,0 +1,110 @@ + +# +# map txt +# +if( HAVE_common_base ) +message( STATUS "Creating target map-server" ) +set( TXT_MAP_HEADERS + "${MAP_SOURCE_DIR}/atcommand.h" + "${MAP_SOURCE_DIR}/battle.h" + "${MAP_SOURCE_DIR}/battleground.h" + "${MAP_SOURCE_DIR}/buyingstore.h" + "${MAP_SOURCE_DIR}/chat.h" + "${MAP_SOURCE_DIR}/chrif.h" + "${MAP_SOURCE_DIR}/clif.h" + "${MAP_SOURCE_DIR}/date.h" + "${MAP_SOURCE_DIR}/duel.h" + "${MAP_SOURCE_DIR}/guild.h" + "${MAP_SOURCE_DIR}/homunculus.h" + "${MAP_SOURCE_DIR}/instance.h" + "${MAP_SOURCE_DIR}/intif.h" + "${MAP_SOURCE_DIR}/itemdb.h" + "${MAP_SOURCE_DIR}/log.h" + "${MAP_SOURCE_DIR}/mail.h" + "${MAP_SOURCE_DIR}/map.h" + "${MAP_SOURCE_DIR}/mapreg.h" + "${MAP_SOURCE_DIR}/mercenary.h" + "${MAP_SOURCE_DIR}/mob.h" + "${MAP_SOURCE_DIR}/npc.h" + "${MAP_SOURCE_DIR}/party.h" + "${MAP_SOURCE_DIR}/path.h" + "${MAP_SOURCE_DIR}/pc.h" + "${MAP_SOURCE_DIR}/pet.h" + "${MAP_SOURCE_DIR}/quest.h" + "${MAP_SOURCE_DIR}/script.h" + "${MAP_SOURCE_DIR}/searchstore.h" + "${MAP_SOURCE_DIR}/skill.h" + "${MAP_SOURCE_DIR}/status.h" + "${MAP_SOURCE_DIR}/storage.h" + "${MAP_SOURCE_DIR}/trade.h" + "${MAP_SOURCE_DIR}/unit.h" + "${MAP_SOURCE_DIR}/vending.h" + ) +set( TXT_MAP_SOURCES + "${MAP_SOURCE_DIR}/atcommand.c" + "${MAP_SOURCE_DIR}/battle.c" + "${MAP_SOURCE_DIR}/battleground.c" + "${MAP_SOURCE_DIR}/buyingstore.c" + "${MAP_SOURCE_DIR}/chat.c" + "${MAP_SOURCE_DIR}/chrif.c" + "${MAP_SOURCE_DIR}/clif.c" + "${MAP_SOURCE_DIR}/date.c" + "${MAP_SOURCE_DIR}/duel.c" + "${MAP_SOURCE_DIR}/guild.c" + "${MAP_SOURCE_DIR}/homunculus.c" + "${MAP_SOURCE_DIR}/instance.c" + "${MAP_SOURCE_DIR}/intif.c" + "${MAP_SOURCE_DIR}/itemdb.c" + "${MAP_SOURCE_DIR}/log.c" + "${MAP_SOURCE_DIR}/mail.c" + "${MAP_SOURCE_DIR}/map.c" + "${MAP_SOURCE_DIR}/mapreg_txt.c" + "${MAP_SOURCE_DIR}/mercenary.c" + "${MAP_SOURCE_DIR}/mob.c" + "${MAP_SOURCE_DIR}/npc.c" + "${MAP_SOURCE_DIR}/npc_chat.c" + "${MAP_SOURCE_DIR}/party.c" + "${MAP_SOURCE_DIR}/path.c" + "${MAP_SOURCE_DIR}/pc.c" + "${MAP_SOURCE_DIR}/pet.c" + "${MAP_SOURCE_DIR}/quest.c" + "${MAP_SOURCE_DIR}/script.c" + "${MAP_SOURCE_DIR}/searchstore.c" + "${MAP_SOURCE_DIR}/skill.c" + "${MAP_SOURCE_DIR}/status.c" + "${MAP_SOURCE_DIR}/storage.c" + "${MAP_SOURCE_DIR}/trade.c" + "${MAP_SOURCE_DIR}/unit.c" + "${MAP_SOURCE_DIR}/vending.c" + ) +set( DEPENDENCIES common_base ) +set( LIBRARIES ${GLOBAL_LIBRARIES} ) +set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ) +set( DEFINITIONS ${GLOBAL_DEFINITIONS} TXT_ONLY ) +if( WITH_PCRE ) + message( STATUS "Using PCRE" ) + list( APPEND LIBRARIES ${PCRE_LIBRARIES} ) + list( APPEND INCLUDE_DIRS ${PCRE_INCLUDE_DIRS} ) + list( APPEND DEFINITIONS PCRE_SUPPORT ) +endif() +set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${TXT_MAP_HEADERS} ${TXT_MAP_SOURCES} ) +source_group( common FILES ${COMMON_BASE_HEADERS} ) +source_group( map FILES ${TXT_MAP_HEADERS} ${TXT_MAP_SOURCES} ) +include_directories( ${INCLUDE_DIRS} ) +add_executable( map-server ${SOURCE_FILES} ) +add_dependencies( map-server ${DEPENDENCIES} ) +target_link_libraries( map-server ${LIBRARIES} ${DEPENDENCIES} ) +set_target_properties( map-server PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" ) +if( WITH_COMPONENT_RUNTIME ) + cpack_add_component( Runtime_mapserver_txt DESCRIPTION "map-server (txt version)" DISPLAY_NAME "map-server" GROUP Runtime ) + install( TARGETS map-server + DESTINATION "." + COMPONENT Runtime_mapserver_txt ) +endif() +message( STATUS "Creating target map-server - done" ) +set( HAVE_map-server ON CACHE BOOL "map-server target is available" ) +mark_as_advanced( HAVE_map-server ) +else() +message( STATUS "Skipping target map-server (requires common_base; optional PCRE)" ) +unset( HAVE_map-server CACHE ) +endif() diff --git a/src/map/unit.c b/src/map/unit.c index 3cec43f70..2165532b4 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -51,8 +51,8 @@ struct unit_data* unit_bl2ud(struct block_list *bl) return NULL; } -static int unit_attack_timer(int tid, unsigned int tick, int id, intptr data); -static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr data); +static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data); +static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data); int unit_walktoxy_sub(struct block_list *bl) { @@ -106,7 +106,7 @@ int unit_walktoxy_sub(struct block_list *bl) return 1; } -static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr data) +static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data) { int i; int x,y,dx,dy; @@ -263,7 +263,7 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr data) return 0; } -static int unit_delay_walktoxy_timer(int tid, unsigned int tick, int id, intptr data) +static int unit_delay_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data) { struct block_list *bl = map_id2bl(id); @@ -327,7 +327,7 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag) if((bl)->type == BL_MOB && (flag)) \ ((TBL_MOB*)(bl))->state.skillstate = ((TBL_MOB*)(bl))->state.aggressive?MSS_FOLLOW:MSS_RUSH; -static int unit_walktobl_sub(int tid, unsigned int tick, int id, intptr data) +static int unit_walktobl_sub(int tid, unsigned int tick, int id, intptr_t data) { struct block_list *bl = map_id2bl(id); struct unit_data *ud = bl?unit_bl2ud(bl):NULL; @@ -847,7 +847,7 @@ int unit_can_move(struct block_list *bl) * Resume running after a walk delay *------------------------------------------*/ -int unit_resume_running(int tid, unsigned int tick, int id, intptr data) +int unit_resume_running(int tid, unsigned int tick, int id, intptr_t data) { struct unit_data *ud = (struct unit_data *)data; @@ -891,7 +891,7 @@ int unit_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int //Resume running after can move again [Kevin] if(ud->state.running) { - add_timer(ud->canmove_tick, unit_resume_running, bl->id, (intptr)ud); + add_timer(ud->canmove_tick, unit_resume_running, bl->id, (intptr_t)ud); } else { @@ -1655,7 +1655,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t return 1; } -static int unit_attack_timer(int tid, unsigned int tick, int id, intptr data) +static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data) { struct block_list *bl; bl = map_id2bl(id); @@ -1881,7 +1881,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, storage_guild_storage_quit(sd,0); sd->state.storage_flag = 0; //Force close it when being warped. if(sd->party_invite>0) - party_reply_invite(sd,sd->party_invite_account,0); + party_reply_invite(sd,sd->party_invite,0); if(sd->guild_invite>0) guild_reply_invite(sd,sd->guild_invite,0); if(sd->guild_alliance>0) diff --git a/src/plugins/console.c b/src/plugins/console.c index bf1a133ca..74c431d32 100644 --- a/src/plugins/console.c +++ b/src/plugins/console.c @@ -126,9 +126,9 @@ PLUGIN_EVENTS_TABLE = { // Imported functions -typedef int (*TimerFunc)(int tid, unsigned int tick, int id, intptr data); +typedef int (*TimerFunc)(int tid, unsigned int tick, int id, intptr_t data); int (*add_timer_func_list)(TimerFunc func, char* name); -int (*add_timer_interval)(unsigned int tick, TimerFunc func, int id, intptr data, int interval); +int (*add_timer_interval)(unsigned int tick, TimerFunc func, int id, intptr_t data, int interval); int (*delete_timer)(int tid, TimerFunc func); unsigned int (*gettick)(void); int (*parse_console)(const char* buf); @@ -423,7 +423,7 @@ WORKER_FUNC_END(getinput) /// Timer function that checks if there's assynchronous input data and feeds parse_console() /// The input reads one line at a time and line terminators are removed. -int console_getinputtimer(int tid, unsigned int tick, int id, intptr data) +int console_getinputtimer(int tid, unsigned int tick, int id, intptr_t data) { char* cmd; size_t len; diff --git a/src/tool/CMakeLists.txt b/src/tool/CMakeLists.txt new file mode 100644 index 000000000..e45586915 --- /dev/null +++ b/src/tool/CMakeLists.txt @@ -0,0 +1,42 @@ + +# +# mapcache +# +if( WITH_ZLIB ) +message( STATUS "Creating target mapcache" ) +set( COMMON_HEADERS + ${COMMON_MINI_HEADERS} + "${COMMON_SOURCE_DIR}/grfio.h" + "${COMMON_SOURCE_DIR}/utils.h" + ) +set( COMMON_SOURCES + ${COMMON_MINI_SOURCES} + "${COMMON_SOURCE_DIR}/grfio.c" + "${COMMON_SOURCE_DIR}/utils.c" + ) +set( MAPCACHE_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/mapcache.c" + ) +set( LIBRARIES ${GLOBAL_LIBRARIES} ${ZLIB_LIBRARIES} ) +set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS} ) +set( DEFINITIONS ${GLOBAL_DEFINITIONS} ${COMMON_MINI_DEFINITIONS} ) +set( SOURCE_FILES ${COMMON_HEADERS} ${COMMON_SOURCES} ${MAPCACHE_SOURCES} ) +source_group( common FILES ${COMMON_HEADERS} ${COMMON_SOURCES} ) +source_group( mapcache FILES ${MAPCACHE_SOURCES} ) +add_executable( mapcache ${SOURCE_FILES} ) +include_directories( ${INCLUDE_DIRS} ) +target_link_libraries( mapcache ${LIBRARIES} ) +set_target_properties( mapcache PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" ) +if( WITH_COMPONENT_RUNTIME ) + cpack_add_component( Runtime_mapcache DESCRIPTION "mapcache generator" DISPLAY_NAME "mapcache" GROUP Runtime ) + install( TARGETS mapcache + DESTINATION "." + COMPONENT Runtime_mapcache ) +endif() +message( STATUS "Creating target mapcache - done" ) +set( HAVE_mapcache ON CACHE BOOL "mapcache target is available" ) +mark_as_advanced( HAVE_mapcache ) +else() +message( STATUS "Skipping target mapcache (requires ZLIB)" ) +unset( HAVE_mapcache CACHE ) +endif() diff --git a/src/tool/mapcache.c b/src/tool/mapcache.c index deec27c4c..f1a7559f1 100644 --- a/src/tool/mapcache.c +++ b/src/tool/mapcache.c @@ -98,7 +98,7 @@ int32 GetLong(const unsigned char* buf) float GetFloat(const unsigned char* buf) { uint32 val = GetULong(buf); - return *((float*)&val); + return *((float*)(void*)&val); } @@ -171,7 +171,7 @@ void cache_map(char *name, struct map_data *m) len = (unsigned long)m->xs*(unsigned long)m->ys*2; write_buf = (unsigned char *)aMalloc(len); // Compress the cells and get the compressed length - compress(write_buf, &len, m->cells, m->xs*m->ys); + encode_zip(write_buf, &len, m->cells, m->xs*m->ys); // Fill the map header strncpy(info.name, name, MAP_NAME_LENGTH); |