1 #include "weapon.h" |
1 #include "weapon.h" |
2 |
2 |
3 #include "../util/inihelper.h" |
3 #include "../util/inihelper.h" |
4 #include "../util/logging.h" |
4 #include "../util/logging.h" |
5 #include "../util/util.h" |
5 #include "../util/util.h" |
|
6 #include "../util/refcounter.h" |
6 |
7 |
7 #include <stdlib.h> |
8 #include <stdlib.h> |
8 #include <ctype.h> |
9 #include <ctype.h> |
9 |
10 #include <string.h> |
10 int set_field(char field[WEAPONS_COUNT+1], const char *line, bool no9) { |
11 |
11 // Validate the new string |
12 static void flib_weaponset_destroy(flib_weaponset *cfg) { |
12 for(int i=0; i<WEAPONS_COUNT && line[i]; i++) { |
|
13 if(line[i] < '0' || line[i] > '9' || (no9 && line[i] == '9')) { |
|
14 flib_log_e("Invalid character in weapon config string \"%.*s\", position %i", WEAPONS_COUNT, line, i); |
|
15 return -1; |
|
16 } |
|
17 } |
|
18 |
|
19 bool lineEnded = false; |
|
20 for(int i=0; i<WEAPONS_COUNT; i++) { |
|
21 if(!lineEnded && !line[i]) { |
|
22 flib_log_w("Incomplete weapon config line \"%s\", filling with zeroes.", line); |
|
23 lineEnded = true; |
|
24 } |
|
25 if(lineEnded) { |
|
26 field[i] = '0'; |
|
27 } else { |
|
28 field[i] = line[i]; |
|
29 } |
|
30 } |
|
31 field[WEAPONS_COUNT] = 0; |
|
32 return 0; |
|
33 } |
|
34 |
|
35 static flib_weaponset *flib_weaponset_create_str(const char *name, const char *loadoutStr, const char *crateProbStr, const char *crateAmmoStr, const char *delayStr) { |
|
36 flib_weaponset *result = NULL; |
|
37 if(!name || !loadoutStr || !crateProbStr || !crateAmmoStr || !delayStr) { |
|
38 flib_log_e("null parameter in flib_weaponset_create_str"); |
|
39 } else { |
|
40 flib_weaponset *newSet = flib_calloc(1, sizeof(flib_weaponset)); |
|
41 char *nameCopy = flib_strdupnull(name); |
|
42 if(newSet && nameCopy) { |
|
43 newSet->name = nameCopy; |
|
44 nameCopy = NULL; |
|
45 bool error = false; |
|
46 error |= set_field(newSet->loadout, loadoutStr, false); |
|
47 error |= set_field(newSet->crateprob, crateProbStr, false); |
|
48 error |= set_field(newSet->crateammo, crateAmmoStr, false); |
|
49 error |= set_field(newSet->delay, delayStr, false); |
|
50 if(!error) { |
|
51 result = newSet; |
|
52 newSet = NULL; |
|
53 } |
|
54 } |
|
55 free(nameCopy); |
|
56 flib_weaponset_destroy(newSet); |
|
57 } |
|
58 return result; |
|
59 } |
|
60 |
|
61 void flib_weaponset_destroy(flib_weaponset *cfg) { |
|
62 if(cfg) { |
13 if(cfg) { |
63 free(cfg->name); |
14 free(cfg->name); |
64 free(cfg); |
15 free(cfg); |
65 } |
16 } |
66 } |
17 } |
67 |
18 |
|
19 static void setField(char field[WEAPONS_COUNT+1], const char *line, int lineLen, bool no9) { |
|
20 if(lineLen>WEAPONS_COUNT) { |
|
21 lineLen = WEAPONS_COUNT; |
|
22 } |
|
23 |
|
24 char min = '0'; |
|
25 char max = no9 ? '8' : '9'; |
|
26 for(int i=0; i<lineLen; i++) { |
|
27 if(line[i] >= min && line[i] <= max) { |
|
28 field[i] = line[i]; |
|
29 } else { |
|
30 flib_log_w("Invalid character in weapon config string \"%.*s\", position %i", lineLen, line, i); |
|
31 field[i] = '0'; |
|
32 } |
|
33 } |
|
34 for(int i=lineLen; i<WEAPONS_COUNT; i++) { |
|
35 field[i] = '0'; |
|
36 } |
|
37 field[WEAPONS_COUNT] = 0; |
|
38 } |
|
39 |
68 flib_weaponset *flib_weaponset_create(const char *name) { |
40 flib_weaponset *flib_weaponset_create(const char *name) { |
69 return flib_weaponset_create_str(name, AMMOLINE_DEFAULT_QT, AMMOLINE_DEFAULT_PROB, AMMOLINE_DEFAULT_CRATE, AMMOLINE_DEFAULT_DELAY); |
|
70 } |
|
71 |
|
72 flib_weaponset *flib_weaponset_from_ini(const char *filename) { |
|
73 flib_weaponset *result = NULL; |
41 flib_weaponset *result = NULL; |
|
42 if(!name) { |
|
43 flib_log_e("null parameter in flib_weaponset_create_str"); |
|
44 } else { |
|
45 flib_weaponset *newSet = flib_weaponset_retain(flib_calloc(1, sizeof(flib_weaponset))); |
|
46 if(newSet) { |
|
47 newSet->name = flib_strdupnull(name); |
|
48 if(newSet->name) { |
|
49 setField(newSet->loadout, "", 0, false); |
|
50 setField(newSet->crateprob, "", 0, false); |
|
51 setField(newSet->crateammo, "", 0, false); |
|
52 setField(newSet->delay, "", 0, false); |
|
53 result = flib_weaponset_retain(newSet); |
|
54 } |
|
55 } |
|
56 flib_weaponset_release(newSet); |
|
57 } |
|
58 return result; |
|
59 } |
|
60 |
|
61 flib_weaponset *flib_weaponset_retain(flib_weaponset *weaponset) { |
|
62 if(weaponset) { |
|
63 flib_retain(&weaponset->_referenceCount, "flib_weaponset"); |
|
64 } |
|
65 return weaponset; |
|
66 } |
|
67 |
|
68 void flib_weaponset_release(flib_weaponset *weaponset) { |
|
69 if(weaponset && flib_release(&weaponset->_referenceCount, "flib_weaponset")) { |
|
70 flib_weaponset_destroy(weaponset); |
|
71 } |
|
72 } |
|
73 |
|
74 static void flib_weaponsetlist_destroy(flib_weaponsetlist *list) { |
|
75 if(list) { |
|
76 for(int i=0; i<list->weaponsetCount; i++) { |
|
77 flib_weaponset_release(list->weaponsets[i]); |
|
78 } |
|
79 free(list); |
|
80 } |
|
81 } |
|
82 |
|
83 static int fillWeaponsetFromIni(flib_weaponsetlist *list, flib_ini *ini, int index) { |
|
84 int result = -1; |
|
85 char *keyname = flib_ini_get_keyname(ini, index); |
|
86 char *decodedKeyname = flib_urldecode(keyname); |
|
87 |
|
88 if(decodedKeyname) { |
|
89 flib_weaponset *set = flib_weaponset_create(decodedKeyname); |
|
90 if(set) { |
|
91 char *value = NULL; |
|
92 if(!flib_ini_get_str(ini, &value, keyname)) { |
|
93 int fieldlen = strlen(value)/4; |
|
94 setField(set->loadout, value, fieldlen, false); |
|
95 setField(set->crateprob, value+1*fieldlen, fieldlen, true); |
|
96 setField(set->delay, value+2*fieldlen, fieldlen, true); |
|
97 setField(set->crateammo, value+3*fieldlen, fieldlen, true); |
|
98 result = flib_weaponsetlist_insert(list, set, list->weaponsetCount); |
|
99 } |
|
100 free(value); |
|
101 } |
|
102 flib_weaponset_release(set); |
|
103 } |
|
104 |
|
105 free(keyname); |
|
106 free(decodedKeyname); |
|
107 return result; |
|
108 } |
|
109 |
|
110 static int fillWeaponsetsFromIni(flib_weaponsetlist *list, flib_ini *ini) { |
|
111 bool error = false; |
|
112 int weaponsets = flib_ini_get_keycount(ini); |
|
113 |
|
114 for(int i=0; i<weaponsets && !error; i++) { |
|
115 error |= fillWeaponsetFromIni(list, ini, i); |
|
116 } |
|
117 return error; |
|
118 } |
|
119 |
|
120 flib_weaponsetlist *flib_weaponsetlist_from_ini(const char *filename) { |
|
121 flib_weaponsetlist *result = NULL; |
74 if(!filename) { |
122 if(!filename) { |
75 flib_log_e("null parameter in flib_weaponset_from_ini"); |
123 flib_log_e("null parameter in flib_weaponsetlist_from_ini"); |
76 } else { |
124 } else { |
77 flib_ini *ini = flib_ini_load(filename); |
125 flib_ini *ini = flib_ini_load(filename); |
78 if(!ini) { |
126 if(!ini) { |
79 flib_log_e("Error loading weapon scheme file %s", filename); |
127 flib_log_e("Missing file %s.", filename); |
80 } else if(!flib_ini_enter_section(ini, "weaponset")) { |
128 } else if(flib_ini_enter_section(ini, "General")) { |
|
129 flib_log_e("Missing section \"General\" in file %s.", filename); |
|
130 } else { |
|
131 flib_weaponsetlist *list = flib_weaponsetlist_create(); |
|
132 if(list) { |
|
133 if(!fillWeaponsetsFromIni(list, ini)) { |
|
134 result = flib_weaponsetlist_retain(list); |
|
135 } |
|
136 } |
|
137 flib_weaponsetlist_release(list); |
|
138 } |
|
139 flib_ini_destroy(ini); |
|
140 } |
|
141 return result; |
|
142 } |
|
143 |
|
144 static bool needsEscape(char c) { |
|
145 return !((c>='0' && c<='9') || (c>='a' && c <='z')); |
|
146 } |
|
147 |
|
148 |
|
149 static int writeWeaponsetToIni(flib_ini *ini, flib_weaponset *set) { |
|
150 int result = -1; |
|
151 char weaponstring[WEAPONS_COUNT*4+1]; |
|
152 strcpy(weaponstring, set->loadout); |
|
153 strcat(weaponstring, set->crateprob); |
|
154 strcat(weaponstring, set->delay); |
|
155 strcat(weaponstring, set->crateammo); |
|
156 |
|
157 char *escapedname = flib_urlencode_pred(set->name, needsEscape); |
|
158 if(escapedname) { |
|
159 result = flib_ini_set_str(ini, escapedname, weaponstring); |
|
160 } |
|
161 free(escapedname); |
|
162 return result; |
|
163 } |
|
164 |
|
165 int flib_weaponsetlist_to_ini(const char *filename, const flib_weaponsetlist *list) { |
|
166 int result = -1; |
|
167 if(!filename || !list) { |
|
168 flib_log_e("null parameter in flib_weaponsetlist_to_ini"); |
|
169 } else { |
|
170 flib_ini *ini = flib_ini_create(NULL); |
|
171 if(ini && !flib_ini_create_section(ini, "General")) { |
81 bool error = false; |
172 bool error = false; |
82 char *name = NULL, *loadout = NULL, *crateprob = NULL, *crateammo = NULL, *delay = NULL; |
173 for(int i=0; i<list->weaponsetCount && !error; i++) { |
83 error |= flib_ini_get_str(ini, &name, "name"); |
174 error |= writeWeaponsetToIni(ini, list->weaponsets[i]); |
84 error |= flib_ini_get_str(ini, &loadout, "loadout"); |
175 } |
85 error |= flib_ini_get_str(ini, &crateprob, "crateprob"); |
176 |
86 error |= flib_ini_get_str(ini, &crateammo, "crateammo"); |
|
87 error |= flib_ini_get_str(ini, &delay, "delay"); |
|
88 |
|
89 if(error) { |
|
90 flib_log_e("Missing key in weapon scheme file %s", filename); |
|
91 } else { |
|
92 result = flib_weaponset_create_str(name, loadout, crateprob, crateammo, delay); |
|
93 } |
|
94 free(name); |
|
95 free(loadout); |
|
96 free(crateprob); |
|
97 free(crateammo); |
|
98 free(delay); |
|
99 } |
|
100 flib_ini_destroy(ini); |
|
101 } |
|
102 return result; |
|
103 } |
|
104 |
|
105 int flib_weaponset_to_ini(const char *filename, const flib_weaponset *set) { |
|
106 int result = -1; |
|
107 if(!filename || !set) { |
|
108 flib_log_e("null parameter in flib_weaponset_to_ini"); |
|
109 } else { |
|
110 flib_ini *ini = flib_ini_create(filename); |
|
111 if(!flib_ini_create_section(ini, "weaponset")) { |
|
112 bool error = false; |
|
113 error |= flib_ini_set_str(ini, "name", set->name); |
|
114 error |= flib_ini_set_str(ini, "loadout", set->loadout); |
|
115 error |= flib_ini_set_str(ini, "crateprob", set->crateprob); |
|
116 error |= flib_ini_set_str(ini, "crateammo", set->crateammo); |
|
117 error |= flib_ini_set_str(ini, "delay", set->delay); |
|
118 if(!error) { |
177 if(!error) { |
119 result = flib_ini_save(ini, filename); |
178 result = flib_ini_save(ini, filename); |
120 } |
179 } |
121 } |
180 } |
122 flib_ini_destroy(ini); |
181 flib_ini_destroy(ini); |
123 } |
182 } |
124 return result; |
183 return result; |
125 } |
184 } |
|
185 |
|
186 flib_weaponsetlist *flib_weaponsetlist_create() { |
|
187 return flib_weaponsetlist_retain(flib_calloc(1, sizeof(flib_weaponsetlist))); |
|
188 } |
|
189 |
|
190 int flib_weaponsetlist_insert(flib_weaponsetlist *list, flib_weaponset *weaponset, int pos) { |
|
191 int result = -1; |
|
192 if(!list || !weaponset || pos < 0 || pos > list->weaponsetCount) { |
|
193 flib_log_e("Invalid parameter in flib_weaponsetlist_insert"); |
|
194 } else { |
|
195 flib_weaponset **newSets = flib_realloc(list->weaponsets, (list->weaponsetCount+1)*sizeof(*list->weaponsets)); |
|
196 if(newSets) { |
|
197 list->weaponsets = newSets; |
|
198 memmove(list->weaponsets+pos+1, list->weaponsets+pos, (list->weaponsetCount-pos)*sizeof(*list->weaponsets)); |
|
199 list->weaponsets[pos] = flib_weaponset_retain(weaponset); |
|
200 list->weaponsetCount++; |
|
201 result = 0; |
|
202 } |
|
203 } |
|
204 return result; |
|
205 } |
|
206 |
|
207 int flib_weaponsetlist_delete(flib_weaponsetlist *list, int pos) { |
|
208 int result = -1; |
|
209 if(!list || pos < 0 || pos >= list->weaponsetCount) { |
|
210 flib_log_e("Invalid parameter in flib_weaponsetlist_delete"); |
|
211 } else { |
|
212 flib_weaponset_release(list->weaponsets[pos]); |
|
213 memmove(list->weaponsets+pos, list->weaponsets+pos+1, (list->weaponsetCount-(pos+1))*sizeof(*list->weaponsets)); |
|
214 list->weaponsets[list->weaponsetCount-1] = NULL; |
|
215 list->weaponsetCount--; |
|
216 |
|
217 // If the realloc fails, just keep using the old buffer... |
|
218 flib_weaponset **newSets = flib_realloc(list->weaponsets, list->weaponsetCount*sizeof(*list->weaponsets)); |
|
219 if(newSets || list->weaponsetCount==1) { |
|
220 list->weaponsets = newSets; |
|
221 } |
|
222 result = 0; |
|
223 } |
|
224 return result; |
|
225 } |
|
226 |
|
227 flib_weaponsetlist *flib_weaponsetlist_retain(flib_weaponsetlist *list) { |
|
228 if(list) { |
|
229 flib_retain(&list->_referenceCount, "flib_weaponsetlist"); |
|
230 } |
|
231 return list; |
|
232 } |
|
233 |
|
234 void flib_weaponsetlist_release(flib_weaponsetlist *list) { |
|
235 if(list && flib_release(&list->_referenceCount, "flib_weaponsetlist")) { |
|
236 flib_weaponsetlist_destroy(list); |
|
237 } |
|
238 } |