int_status.c 4.9 KB

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