1 /*
2 * Hedgewars, a free turn based strategy game
3 * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20 #include "team.h"
21
22 #include "../util/inihelper.h"
23 #include "../util/util.h"
24 #include "../util/logging.h"
25
26 #include <string.h>
27 #include <stdlib.h>
28
from_ini_handleError(flib_team * result,flib_ini * settingfile)29 static flib_team *from_ini_handleError(flib_team *result, flib_ini *settingfile) {
30 flib_ini_destroy(settingfile);
31 flib_team_destroy(result);
32 return NULL;
33 }
34
flib_team_from_ini(const char * filename)35 flib_team *flib_team_from_ini(const char *filename) {
36 if(log_badargs_if(filename==NULL)) {
37 return NULL;
38 }
39
40 flib_team *result = flib_calloc(1, sizeof(flib_team));
41 flib_ini *ini = NULL;
42
43 if(!result) {
44 return from_ini_handleError(result, ini);
45 }
46
47 ini = flib_ini_load(filename);
48 if(!ini) {
49 flib_log_e("Error loading team file %s", filename);
50 return from_ini_handleError(result, ini);
51 }
52
53 if(flib_ini_enter_section(ini, "team")) {
54 flib_log_e("Missing section \"Team\" in team file %s", filename);
55 return from_ini_handleError(result, ini);
56 }
57 bool error = false;
58 error |= flib_ini_get_str(ini, &result->name, "name");
59 error |= flib_ini_get_str(ini, &result->grave, "grave");
60 error |= flib_ini_get_str(ini, &result->fort, "fort");
61 error |= flib_ini_get_str(ini, &result->voicepack, "voicepack");
62 error |= flib_ini_get_str(ini, &result->flag, "flag");
63 error |= flib_ini_get_int(ini, &result->rounds, "rounds");
64 error |= flib_ini_get_int(ini, &result->wins, "wins");
65 error |= flib_ini_get_int(ini, &result->campaignProgress, "campaignprogress");
66
67 int difficulty = 0;
68 error |= flib_ini_get_int(ini, &difficulty, "difficulty");
69
70 if(error) {
71 flib_log_e("Missing or malformed entry in section \"Team\" in file %s", filename);
72 return from_ini_handleError(result, ini);
73 }
74
75 for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
76 char sectionName[32];
77 if(snprintf(sectionName, sizeof(sectionName), "hedgehog%i", i) <= 0) {
78 return from_ini_handleError(result, ini);
79 }
80 if(flib_ini_enter_section(ini, sectionName)) {
81 flib_log_e("Missing section \"%s\" in team file %s", sectionName, filename);
82 return from_ini_handleError(result, ini);
83 }
84 flib_hog *hog = &result->hogs[i];
85 error |= flib_ini_get_str(ini, &hog->name, "name");
86 error |= flib_ini_get_str(ini, &hog->hat, "hat");
87 error |= flib_ini_get_int(ini, &hog->rounds, "rounds");
88 error |= flib_ini_get_int(ini, &hog->kills, "kills");
89 error |= flib_ini_get_int(ini, &hog->deaths, "deaths");
90 error |= flib_ini_get_int(ini, &hog->suicides, "suicides");
91 result->hogs[i].difficulty = difficulty;
92 result->hogs[i].initialHealth = TEAM_DEFAULT_HEALTH;
93
94 if(error) {
95 flib_log_e("Missing or malformed entry in section \"%s\" in file %s", sectionName, filename);
96 return from_ini_handleError(result, ini);
97 }
98 }
99
100 if(!flib_ini_enter_section(ini, "binds")) {
101 result->bindingCount = flib_ini_get_keycount(ini);
102 if(result->bindingCount<0) {
103 flib_log_e("Error reading bindings from file %s", filename);
104 result->bindingCount = 0;
105 }
106 result->bindings = flib_calloc(result->bindingCount, sizeof(flib_binding));
107 if(!result->bindings) {
108 return from_ini_handleError(result, ini);
109 }
110 for(int i=0; i<result->bindingCount; i++) {
111 char *keyname = flib_ini_get_keyname(ini, i);
112 if(!keyname) {
113 error = true;
114 } else {
115 result->bindings[i].action = flib_urldecode(keyname);
116 error |= !result->bindings[i].action;
117 error |= flib_ini_get_str(ini, &result->bindings[i].binding, keyname);
118 }
119 free(keyname);
120 }
121 }
122
123 if(error) {
124 flib_log_e("Error reading team file %s", filename);
125 return from_ini_handleError(result, ini);
126 }
127
128 flib_ini_destroy(ini);
129 return result;
130 }
131
flib_team_destroy(flib_team * team)132 void flib_team_destroy(flib_team *team) {
133 if(team) {
134 for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
135 free(team->hogs[i].name);
136 free(team->hogs[i].hat);
137 flib_weaponset_destroy(team->hogs[i].weaponset);
138 }
139 free(team->name);
140 free(team->grave);
141 free(team->fort);
142 free(team->voicepack);
143 free(team->flag);
144 if(team->bindings) {
145 for(int i=0; i<team->bindingCount; i++) {
146 free(team->bindings[i].action);
147 free(team->bindings[i].binding);
148 }
149 }
150 free(team->bindings);
151 free(team->ownerName);
152 free(team);
153 }
154 }
155
writeTeamSection(const flib_team * team,flib_ini * ini)156 static int writeTeamSection(const flib_team *team, flib_ini *ini) {
157 if(flib_ini_create_section(ini, "team")) {
158 return -1;
159 }
160 bool error = false;
161 error |= flib_ini_set_str(ini, "name", team->name);
162 error |= flib_ini_set_str(ini, "grave", team->grave);
163 error |= flib_ini_set_str(ini, "fort", team->fort);
164 error |= flib_ini_set_str(ini, "voicepack", team->voicepack);
165 error |= flib_ini_set_str(ini, "flag", team->flag);
166 error |= flib_ini_set_int(ini, "rounds", team->rounds);
167 error |= flib_ini_set_int(ini, "wins", team->wins);
168 error |= flib_ini_set_int(ini, "campaignprogress", team->campaignProgress);
169 error |= flib_ini_set_int(ini, "difficulty", team->hogs[0].difficulty);
170 return error;
171 }
172
writeHogSections(const flib_team * team,flib_ini * ini)173 static int writeHogSections(const flib_team *team, flib_ini *ini) {
174 for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
175 const flib_hog *hog = &team->hogs[i];
176 char sectionName[32];
177 if(snprintf(sectionName, sizeof(sectionName), "hedgehog%i", i) <= 0) {
178 return -1;
179 }
180 if(flib_ini_create_section(ini, sectionName)) {
181 return -1;
182 }
183 bool error = false;
184 error |= flib_ini_set_str(ini, "name", hog->name);
185 error |= flib_ini_set_str(ini, "hat", hog->hat);
186 error |= flib_ini_set_int(ini, "rounds", hog->rounds);
187 error |= flib_ini_set_int(ini, "kills", hog->kills);
188 error |= flib_ini_set_int(ini, "deaths", hog->deaths);
189 error |= flib_ini_set_int(ini, "suicides", hog->suicides);
190 if(error) {
191 return error;
192 }
193 }
194 return 0;
195 }
196
writeBindingSection(const flib_team * team,flib_ini * ini)197 static int writeBindingSection(const flib_team *team, flib_ini *ini) {
198 if(team->bindingCount == 0) {
199 return 0;
200 }
201 if(flib_ini_create_section(ini, "binds")) {
202 return -1;
203 }
204 for(int i=0; i<team->bindingCount; i++) {
205 bool error = false;
206 char *action = flib_urlencode(team->bindings[i].action);
207 if(action) {
208 error |= flib_ini_set_str(ini, action, team->bindings[i].binding);
209 free(action);
210 } else {
211 error = true;
212 }
213 if(error) {
214 return error;
215 }
216 }
217 return 0;
218 }
219
flib_team_to_ini(const char * filename,const flib_team * team)220 int flib_team_to_ini(const char *filename, const flib_team *team) {
221 int result = -1;
222 if(!log_badargs_if2(filename==NULL, team==NULL)) {
223 flib_ini *ini = flib_ini_create(filename);
224 bool error = false;
225 error |= writeTeamSection(team, ini);
226 error |= writeHogSections(team, ini);
227 error |= writeBindingSection(team, ini);
228 if(!error) {
229 result = flib_ini_save(ini, filename);
230 }
231 flib_ini_destroy(ini);
232 }
233 return result;
234 }
235
flib_team_set_weaponset(flib_team * team,const flib_weaponset * set)236 int flib_team_set_weaponset(flib_team *team, const flib_weaponset *set) {
237 if(team) {
238 for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
239 flib_weaponset_destroy(team->hogs[i].weaponset);
240 team->hogs[i].weaponset = flib_weaponset_copy(set);
241 if(set && !team->hogs[i].weaponset) {
242 return -1;
243 }
244 }
245 }
246 return 0;
247 }
248
flib_team_set_health(flib_team * team,int health)249 void flib_team_set_health(flib_team *team, int health) {
250 if(team) {
251 for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
252 team->hogs[i].initialHealth = health;
253 }
254 }
255 }
256
strdupWithError(const char * in,bool * error)257 static char *strdupWithError(const char *in, bool *error) {
258 char *out = flib_strdupnull(in);
259 if(in && !out) {
260 *error = true;
261 }
262 return out;
263 }
264
flib_team_copy(const flib_team * team)265 flib_team *flib_team_copy(const flib_team *team) {
266 flib_team *result = NULL;
267 if(team) {
268 flib_team *tmpTeam = flib_calloc(1, sizeof(flib_team));
269 if(tmpTeam) {
270 bool error = false;
271
272 for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
273 tmpTeam->hogs[i].name = strdupWithError(team->hogs[i].name, &error);
274 tmpTeam->hogs[i].hat = strdupWithError(team->hogs[i].hat, &error);
275 tmpTeam->hogs[i].rounds = team->hogs[i].rounds;
276 tmpTeam->hogs[i].kills = team->hogs[i].kills;
277 tmpTeam->hogs[i].deaths = team->hogs[i].deaths;
278 tmpTeam->hogs[i].suicides = team->hogs[i].suicides;
279 tmpTeam->hogs[i].difficulty = team->hogs[i].difficulty;
280 tmpTeam->hogs[i].initialHealth = team->hogs[i].initialHealth;
281 tmpTeam->hogs[i].weaponset = flib_weaponset_copy(team->hogs[i].weaponset);
282 if(team->hogs[i].weaponset && !tmpTeam->hogs[i].weaponset) {
283 error = true;
284 }
285 }
286
287 tmpTeam->name = strdupWithError(team->name, &error);
288 tmpTeam->grave = strdupWithError(team->grave, &error);
289 tmpTeam->fort = strdupWithError(team->fort, &error);
290 tmpTeam->voicepack = strdupWithError(team->voicepack, &error);
291 tmpTeam->flag = strdupWithError(team->flag, &error);
292 tmpTeam->ownerName = strdupWithError(team->ownerName, &error);
293
294 tmpTeam->bindingCount = team->bindingCount;
295 if(team->bindings) {
296 tmpTeam->bindings = flib_calloc(team->bindingCount, sizeof(flib_binding));
297 if(tmpTeam->bindings) {
298 for(int i=0; i<tmpTeam->bindingCount; i++) {
299 tmpTeam->bindings[i].action = strdupWithError(team->bindings[i].action, &error);
300 tmpTeam->bindings[i].binding = strdupWithError(team->bindings[i].binding, &error);
301 }
302 } else {
303 error = true;
304 }
305 }
306
307 tmpTeam->rounds = team->rounds;
308 tmpTeam->wins = team->wins;
309 tmpTeam->campaignProgress = team->campaignProgress;
310
311 tmpTeam->colorIndex = team->colorIndex;
312 tmpTeam->hogsInGame = team->hogsInGame;
313 tmpTeam->remoteDriven = team->remoteDriven;
314
315 if(!error) {
316 result = tmpTeam;
317 tmpTeam = 0;
318 }
319 }
320 flib_team_destroy(tmpTeam);
321 }
322 return result;
323 }
324