summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorshennetsind <ind@henn.et>2014-02-02 18:35:15 -0200
committershennetsind <ind@henn.et>2014-02-02 18:35:15 -0200
commit9132878d911cfe720eaad94ad3d4a5dd11958f99 (patch)
treee24e9668836c9cf8d6856b12a8f75a261502a3f4 /src
parent00ef66fb9261a50e6761cf77c11e7f468494c95f (diff)
downloadhercules-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>
Diffstat (limited to 'src')
-rw-r--r--src/char/char.c34
-rw-r--r--src/map/chrif.c46
-rw-r--r--src/map/chrif.h4
-rw-r--r--src/map/status.c8
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.