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