summaryrefslogtreecommitdiff
path: root/src/char/int_status.c
blob: d03797e1d2923ac4cb318f113e804ad7674090f7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder

#include <stdio.h>

#include "int_status.h"
#include "../common/db.h"
#include "../common/lock.h"
#include "../common/malloc.h"
#include "../common/showmsg.h"

static struct dbt * scdata_db = NULL;	//Contains all the status change data in-memory. [Skotlex]
char scdata_txt[1024]="save/scdata.txt"; //By [Skotlex]

#ifdef ENABLE_SC_SAVING
static void* create_scdata(DBKey key, va_list args) {
	struct scdata *data;
	data = aCalloc(1, sizeof(struct scdata));
	data->account_id = va_arg(args, int);
	data->char_id = key.i;
	return data;
}

/*==========================================
 * Loads status change data of the player given. [Skotlex]
 *------------------------------------------*/
struct scdata* status_search_scdata(int aid, int cid)
{
	struct scdata *data;
	data = scdata_db->ensure(scdata_db, i2key(cid), create_scdata, aid);
	return data;
}

/*==========================================
 * Deletes status change data of the player given. [Skotlex]
 * Should be invoked after the data of said player was successfully loaded.
 *------------------------------------------*/
void status_delete_scdata(int aid, int cid)
{
	struct scdata *scdata = idb_remove(scdata_db, cid);
	if (scdata)
	{
		if (scdata->data)
			aFree(scdata->data);
		aFree(scdata);
	}
}


static void inter_status_tostr(char* line, struct scdata *sc_data)
{
	int i, len;

	len = sprintf(line, "%d,%d,%d\t", sc_data->account_id, sc_data->char_id, sc_data->count);
	for(i = 0; i < sc_data->count; i++) {
		len += sprintf(line + len, "%d,%d,%d,%d,%d,%d\t", sc_data->data[i].type, sc_data->data[i].tick,
			sc_data->data[i].val1, sc_data->data[i].val2, sc_data->data[i].val3, sc_data->data[i].val4);
	}
	return;
}

static int inter_scdata_fromstr(char *line, struct scdata *sc_data)
{
	int i, len, next;
	
	if (sscanf(line,"%d,%d,%d\t%n",&sc_data->account_id, &sc_data->char_id, &sc_data->count, &next) < 3)
		return 0;

	if (sc_data->count < 1)
		return 0;
	
	sc_data->data = aCalloc(sc_data->count, sizeof (struct status_change_data));

	for (i = 0; i < sc_data->count; i++)
	{
		if (sscanf(line + next, "%hu,%d,%d,%d,%d,%d\t%n", &sc_data->data[i].type, &sc_data->data[i].tick,
			&sc_data->data[i].val1, &sc_data->data[i].val2, &sc_data->data[i].val3, &sc_data->data[i].val4, &len) < 6)
		{
			aFree(sc_data->data);
			return 0;
		}
		next+=len;
	}
	return 1;
}
/*==========================================
 * Loads all scdata from the given filename.
 *------------------------------------------*/
void status_load_scdata(const char* filename)
{
	FILE *fp;
	int sd_count=0, sc_count=0;
	char line[8192];
	struct scdata *sc;

	if ((fp = fopen(filename, "r")) == NULL) {
		ShowError("status_load_scdata: Cannot open file %s!\n", filename);
		return;
	}

	while(fgets(line, sizeof(line), fp))
	{
		sc = (struct scdata*)aCalloc(1, sizeof(struct scdata));
		if (inter_scdata_fromstr(line, sc)) {
			sd_count++;
			sc_count+= sc->count;
			sc = idb_put(scdata_db, sc->char_id, sc);
			if (sc) {
				ShowError("Duplicate entry in %s for character %d\n", filename, sc->char_id);
				if (sc->data) aFree(sc->data);
				aFree(sc);
			}
		} else {
			ShowError("status_load_scdata: Broken line data: %s\n", line);
			aFree(sc);
		}
	}
	fclose(fp);
	ShowStatus("Loaded %d saved status changes for %d characters.\n", sc_count, sd_count);
}

static int inter_status_save_sub(DBKey key, void *data, va_list ap) {
	char line[8192];
	struct scdata * sc_data;
	FILE *fp;

	sc_data = (struct scdata *)data;
	if (sc_data->count < 1)
		return 0;
	
	fp = va_arg(ap, FILE *);
	inter_status_tostr(line, sc_data);
	fprintf(fp, "%s" RETCODE, line);
	return 0;
}

/*==========================================
 * Saves all scdata to the given filename.
 *------------------------------------------*/
void inter_status_save()
{
	FILE *fp;
	int lock;

	if ((fp = lock_fopen(scdata_txt, &lock)) == NULL) {
		ShowError("int_status: can't write [%s] !!! data is lost !!!\n", scdata_txt);
		return;
	}
	scdata_db->foreach(scdata_db, inter_status_save_sub, fp);
	lock_fclose(fp,scdata_txt, &lock);
}

/*==========================================
 * Initializes db.
 *------------------------------------------*/
void status_init()
{
	scdata_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int));
	status_load_scdata(scdata_txt);
}

/*==========================================
 * Frees up memory.
 *------------------------------------------*/
static int scdata_db_final(DBKey k,void *d,va_list ap)
{
	struct scdata *data = (struct scdata*)d;
	if (data->data)
		aFree(data->data);
	aFree(data);
	return 0;
}

/*==========================================
 * Final cleanup.
 *------------------------------------------*/
void status_final(void)
{
	scdata_db->destroy(scdata_db, scdata_db_final);
}

#endif //ENABLE_SC_SAVING