diff options
author | shennetsind <ind@henn.et> | 2014-02-02 18:35:15 -0200 |
---|---|---|
committer | shennetsind <ind@henn.et> | 2014-02-02 18:35:15 -0200 |
commit | 9132878d911cfe720eaad94ad3d4a5dd11958f99 (patch) | |
tree | e24e9668836c9cf8d6856b12a8f75a261502a3f4 | |
parent | 00ef66fb9261a50e6761cf77c11e7f468494c95f (diff) | |
download | hercules-9132878d911cfe720eaad94ad3d4a5dd11958f99.tar.gz hercules-9132878d911cfe720eaad94ad3d4a5dd11958f99.tar.bz2 hercules-9132878d911cfe720eaad94ad3d4a5dd11958f99.tar.xz hercules-9132878d911cfe720eaad94ad3d4a5dd11958f99.zip |
Fixed Bug 7962
Fixed issue with "permanent" (durationless) status changes (such as carts) integrity caused on server shutdown.
Special Thanks to Haru!
http://hercules.ws/board/tracker/issue-7962-command-at/
Signed-off-by: shennetsind <ind@henn.et>
-rw-r--r-- | src/char/char.c | 34 | ||||
-rw-r--r-- | src/map/chrif.c | 46 | ||||
-rw-r--r-- | src/map/chrif.h | 4 | ||||
-rw-r--r-- | src/map/status.c | 8 |
4 files changed, 91 insertions, 1 deletions
diff --git a/src/char/char.c b/src/char/char.c index efe02031f..709148db1 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -3688,6 +3688,40 @@ int parse_frommap(int fd) RFIFOFLUSH(fd); } break; + + /* individual sc data insertion/update */ + case 0x2740: + if( RFIFOREST(fd) < 28 ) + return 0; + else { + int account_id = RFIFOL(fd, 2), char_id = RFIFOL(fd, 6), + val1 = RFIFOL(fd, 12), val2 = RFIFOL(fd, 16), + val3 = RFIFOL(fd, 20), val4 = RFIFOL(fd, 24); + short type = RFIFOW(fd, 10); + + if( SQL_ERROR == SQL->Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`char_id`,`type`,`tick`,`val1`,`val2`,`val3`,`val4`) VALUES ('%d','%d','%d',-1,'%d','%d','%d','%d')", + scdata_db, account_id, char_id, type, val1, val2, val3, val4) ) + Sql_ShowDebug(sql_handle); + + RFIFOSKIP(fd, 28); + } + break; + + /* individual sc data delete */ + case 0x2741: + if( RFIFOREST(fd) < 12 ) + return 0; + else { + int account_id = RFIFOL(fd, 2), char_id = RFIFOL(fd, 6); + short type = RFIFOW(fd, 10); + + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id` = '%d' AND `type` = '%d' LIMIT 1", + scdata_db, account_id, char_id, type) ) + Sql_ShowDebug(sql_handle); + + RFIFOSKIP(fd, 12); + } + break; default: diff --git a/src/map/chrif.c b/src/map/chrif.c index 3dc35fc68..c55b241e6 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -1561,6 +1561,50 @@ void chrif_send_report(char* buf, int len) { } /** + * Sends a single scdata for saving into char server, meant to ensure integrity of durationless conditions + **/ +void chrif_save_scdata_single(int account_id, int char_id, short type, struct status_change_entry *sce) { + + if( !chrif->fd ) + return; + + WFIFOHEAD(chrif->fd, 28); + + WFIFOW(chrif->fd, 0) = 0x2740; + WFIFOL(chrif->fd, 2) = account_id; + WFIFOL(chrif->fd, 6) = char_id; + WFIFOW(chrif->fd, 10) = type; + WFIFOL(chrif->fd, 12) = sce->val1; + WFIFOL(chrif->fd, 16) = sce->val2; + WFIFOL(chrif->fd, 20) = sce->val3; + WFIFOL(chrif->fd, 24) = sce->val4; + + WFIFOSET(chrif->fd, 28); + +} +/** + * Sends a single scdata deletion request into char server, meant to ensure integrity of durationless conditions + **/ +void chrif_del_scdata_single(int account_id, int char_id, short type) { + + if( !chrif->fd ) { + ShowError("MAYDAY! failed to delete status %d from CID:%d/AID:%d\n",type,char_id,account_id); + return; + } + + + WFIFOHEAD(chrif->fd, 12); + + WFIFOW(chrif->fd, 0) = 0x2741; + WFIFOL(chrif->fd, 2) = account_id; + WFIFOL(chrif->fd, 6) = char_id; + WFIFOW(chrif->fd, 10) = type; + + WFIFOSET(chrif->fd, 12); + +} + +/** ` * @see DBApply */ int auth_db_final(DBKey key, DBData *data, va_list ap) { @@ -1728,4 +1772,6 @@ void chrif_defaults(void) { chrif->on_ready = chrif_on_ready; chrif->on_disconnect = chrif_on_disconnect; chrif->parse = chrif_parse; + chrif->save_scdata_single = chrif_save_scdata_single; + chrif->del_scdata_single = chrif_del_scdata_single; } diff --git a/src/map/chrif.h b/src/map/chrif.h index 59e45a2ea..25e955604 100644 --- a/src/map/chrif.h +++ b/src/map/chrif.h @@ -9,6 +9,8 @@ #include <time.h> #include "map.h" //TBL_stuff +struct status_change_entry; + /** * Defines **/ @@ -140,6 +142,8 @@ struct chrif_interface { void (*on_ready) (void); void (*on_disconnect) (void); int (*parse) (int fd); + void (*save_scdata_single) (int account_id, int char_id, short type, struct status_change_entry *sce); + void (*del_scdata_single) (int account_id, int char_id, short type); }; struct chrif_interface *chrif; diff --git a/src/map/status.c b/src/map/status.c index 2b0aee97b..4114bc859 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -9142,8 +9142,11 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val sce->val4 = val4; if (tick >= 0) sce->timer = timer->add(timer->gettick() + tick, status->change_timer, bl->id, type); - else + else { sce->timer = INVALID_TIMER; //Infinite duration + if( sd ) + chrif->save_scdata_single(sd->status.account_id,sd->status.char_id,type,sce); + } if (calc_flag) status_calc_bl(bl,calc_flag); @@ -9324,6 +9327,9 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const if (sce->timer != tid && tid != INVALID_TIMER) return 0; + if( sd && sce->timer == INVALID_TIMER ) + chrif->del_scdata_single(sd->status.account_id,sd->status.char_id,type); + if (tid == INVALID_TIMER) { if (type == SC_ENDURE && sce->val4) //Do not end infinite endure. |