int_status.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #include <stdio.h>
  4. #include "int_status.h"
  5. #include "../common/db.h"
  6. #include "../common/lock.h"
  7. #include "../common/malloc.h"
  8. #include "../common/showmsg.h"
  9. static struct dbt * scdata_db = NULL; //Contains all the status change data in-memory. [Skotlex]
  10. char scdata_txt[1024]="save/scdata.txt"; //By [Skotlex]
  11. #ifdef ENABLE_SC_SAVING
  12. static void* create_scdata(DBKey key, va_list args) {
  13. struct scdata *data;
  14. data = aCalloc(1, sizeof(struct scdata));
  15. data->account_id = va_arg(args, int);
  16. data->char_id = key.i;
  17. return data;
  18. }
  19. /*==========================================
  20. * Loads status change data of the player given. [Skotlex]
  21. *------------------------------------------*/
  22. struct scdata* status_search_scdata(int aid, int cid)
  23. {
  24. struct scdata *data;
  25. data = scdata_db->ensure(scdata_db, i2key(cid), create_scdata, aid);
  26. return data;
  27. }
  28. /*==========================================
  29. * Deletes status change data of the player given. [Skotlex]
  30. * Should be invoked after the data of said player was successfully loaded.
  31. *------------------------------------------*/
  32. void status_delete_scdata(int aid, int cid)
  33. {
  34. struct scdata *scdata = idb_remove(scdata_db, cid);
  35. if (scdata)
  36. {
  37. if (scdata->data)
  38. aFree(scdata->data);
  39. aFree(scdata);
  40. }
  41. }
  42. static void inter_status_tostr(char* line, struct scdata *sc_data)
  43. {
  44. int i, len;
  45. len = sprintf(line, "%d,%d,%d\t", sc_data->account_id, sc_data->char_id, sc_data->count);
  46. for(i = 0; i < sc_data->count; i++) {
  47. len += sprintf(line + len, "%d,%d,%d,%d,%d,%d\t", sc_data->data[i].type, sc_data->data[i].tick,
  48. sc_data->data[i].val1, sc_data->data[i].val2, sc_data->data[i].val3, sc_data->data[i].val4);
  49. }
  50. return;
  51. }
  52. static int inter_scdata_fromstr(char *line, struct scdata *sc_data)
  53. {
  54. int i, len, next;
  55. if (sscanf(line,"%d,%d,%d\t%n",&sc_data->account_id, &sc_data->char_id, &sc_data->count, &next) < 3)
  56. return 0;
  57. if (sc_data->count < 1)
  58. return 0;
  59. sc_data->data = aCalloc(sc_data->count, sizeof (struct status_change_data));
  60. for (i = 0; i < sc_data->count; i++)
  61. {
  62. if (sscanf(line + next, "%hu,%d,%d,%d,%d,%d\t%n", &sc_data->data[i].type, &sc_data->data[i].tick,
  63. &sc_data->data[i].val1, &sc_data->data[i].val2, &sc_data->data[i].val3, &sc_data->data[i].val4, &len) < 6)
  64. {
  65. aFree(sc_data->data);
  66. return 0;
  67. }
  68. next+=len;
  69. }
  70. return 1;
  71. }
  72. /*==========================================
  73. * Loads all scdata from the given filename.
  74. *------------------------------------------*/
  75. void status_load_scdata(const char* filename)
  76. {
  77. FILE *fp;
  78. int sd_count=0, sc_count=0;
  79. char line[8192];
  80. struct scdata *sc;
  81. if ((fp = fopen(filename, "r")) == NULL) {
  82. ShowError("status_load_scdata: Cannot open file %s!\n", filename);
  83. return;
  84. }
  85. while(fgets(line, sizeof(line) - 1, fp)) {
  86. sc = (struct scdata*)aCalloc(1, sizeof(struct scdata));
  87. if (inter_scdata_fromstr(line, sc)) {
  88. sd_count++;
  89. sc_count+= sc->count;
  90. sc = idb_put(scdata_db, sc->char_id, sc);
  91. if (sc) {
  92. ShowError("Duplicate entry in %s for character %d\n", filename, sc->char_id);
  93. if (sc->data) aFree(sc->data);
  94. aFree(sc);
  95. }
  96. } else {
  97. ShowError("status_load_scdata: Broken line data: %s\n", line);
  98. aFree(sc);
  99. }
  100. }
  101. fclose(fp);
  102. ShowStatus("Loaded %d saved status changes for %d characters.\n", sc_count, sd_count);
  103. }
  104. static int inter_status_save_sub(DBKey key, void *data, va_list ap) {
  105. char line[8192];
  106. struct scdata * sc_data;
  107. FILE *fp;
  108. sc_data = (struct scdata *)data;
  109. if (sc_data->count < 1)
  110. return 0;
  111. fp = va_arg(ap, FILE *);
  112. inter_status_tostr(line, sc_data);
  113. fprintf(fp, "%s" RETCODE, line);
  114. return 0;
  115. }
  116. /*==========================================
  117. * Saves all scdata to the given filename.
  118. *------------------------------------------*/
  119. void inter_status_save()
  120. {
  121. FILE *fp;
  122. int lock;
  123. if ((fp = lock_fopen(scdata_txt, &lock)) == NULL) {
  124. ShowError("int_status: can't write [%s] !!! data is lost !!!\n", scdata_txt);
  125. return;
  126. }
  127. scdata_db->foreach(scdata_db, inter_status_save_sub, fp);
  128. lock_fclose(fp,scdata_txt, &lock);
  129. }
  130. /*==========================================
  131. * Initializes db.
  132. *------------------------------------------*/
  133. void status_init()
  134. {
  135. scdata_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int));
  136. status_load_scdata(scdata_txt);
  137. }
  138. /*==========================================
  139. * Frees up memory.
  140. *------------------------------------------*/
  141. static int scdata_db_final(DBKey k,void *d,va_list ap)
  142. {
  143. struct scdata *data = (struct scdata*)d;
  144. if (data->data)
  145. aFree(data->data);
  146. aFree(data);
  147. return 0;
  148. }
  149. /*==========================================
  150. * Final cleanup.
  151. *------------------------------------------*/
  152. void status_final(void)
  153. {
  154. scdata_db->destroy(scdata_db, scdata_db_final);
  155. }
  156. #endif //ENABLE_SC_SAVING