Atrinik Server  4.0
region.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
32 #include <global.h>
33 #include <toolkit/string.h>
34 #include <object.h>
35 
38 
39 static region_struct *region_get(void);
40 static void region_free(region_struct *region);
41 static void region_add(region_struct *region);
42 static void region_assign_parents(void);
43 
47 void regions_init(void)
48 {
49  FILE *fp;
50  char filename[MAX_BUF];
51  region_struct *region;
52  char buf[HUGE_BUF * 4], msgbuf[HUGE_BUF], *key, *value, *end;
53 
54  /* Only do this once */
55  if (first_region != NULL) {
56  return;
57  }
58 
59  snprintf(filename, sizeof(filename), "%s/regions.reg", settings.mapspath);
60  fp = fopen(filename, "r");
61 
62  if (fp == NULL) {
63  LOG(ERROR, "Can't open regions file: %s.", filename);
64  exit(1);
65  }
66 
67  region = NULL;
68 
69  while (fgets(buf, sizeof(buf), fp)) {
70  key = buf;
71 
72  while (isspace(*key)) {
73  key++;
74  }
75 
76  end = strchr(buf, '\n');
77 
78  if (end != NULL) {
79  *end = '\0';
80  }
81 
82  /* Empty line or a comment */
83  if (*key == '\0' || *key == '#') {
84  continue;
85  }
86 
87  value = strchr(key, ' ');
88 
89  if (value != NULL) {
90  *value = '\0';
91  value++;
92 
93  while (isspace(*value)) {
94  value++;
95  }
96  }
97 
98  /* When there is no region allocated yet, we expect 'region xxx'. */
99  if (region == NULL) {
100  if (strcmp(key, "region") == 0 && !string_isempty(value)) {
101  region = region_get();
102  region->name = estrdup(value);
103  } else {
104  LOG(ERROR, "Parsing error: %s %s", buf,
105  value ? value : "");
106  exit(1);
107  }
108 
109  continue;
110  } else if (value == NULL) {
111  if (strcmp(key, "msg") == 0) {
112  msgbuf[0] = '\0';
113 
114  while (fgets(buf, sizeof(buf), fp)) {
115  if (strcmp(buf, "endmsg\n") == 0) {
116  break;
117  }
118 
119  snprintfcat(VS(msgbuf), "%s", buf);
120  }
121 
122  if (msgbuf[0] != '\0') {
123  region->msg = estrdup(msgbuf);
124  }
125  } else if (strcmp(key, "end") == 0) {
126  region_add(region);
127  region = NULL;
128  } else {
129  LOG(ERROR, "Parsing error: %s %s", buf,
130  value ? value : "");
131  exit(1);
132  }
133 
134  continue;
135  } else if (strcmp(key, "parent") == 0) {
136  region->parent_name = estrdup(value);
137  } else if (strcmp(key, "longname") == 0) {
138  region->longname = estrdup(value);
139  } else if (strcmp(key, "map_first") == 0) {
140  region->map_first = estrdup(value);
141  } else if (strcmp(key, "map_bg") == 0) {
142  region->map_bg = estrdup(value);
143  } else if (strcmp(key, "jail") == 0) {
144  char path[MAX_BUF];
145  int x, y;
146 
147  /* Jail entries are of the form: /path/to/map x y */
148  if (sscanf(value, "%255[^ ] %d %d", path, &x, &y) != 3) {
149  LOG(ERROR, "Parsing error: %s %s", buf,
150  value ? value : "");
151  exit(1);
152  }
153 
154  region->jailmap = estrdup(path);
155  region->jailx = x;
156  region->jaily = y;
157  } else if (strcmp(key, "child_maps") == 0) {
158  region->child_maps = KEYWORD_IS_TRUE(value);
159  } else {
160  LOG(ERROR, "Parsing error: %s %s", buf,
161  value ? value : "");
162  exit(1);
163  }
164  }
165 
167 
168  fclose(fp);
169 
170  if (region != NULL) {
171  LOG(ERROR, "Region block without end: %s", region->name);
172  exit(1);
173  }
174 }
175 
179 void regions_free(void)
180 {
181  region_struct *region, *next;
182 
183  for (region = first_region; region != NULL; region = next) {
184  next = region->next;
185  region_free(region);
186  }
187 }
188 
195 {
196  return ecalloc(1, sizeof(region_struct));
197 }
198 
204 static void region_free(region_struct *region)
205 {
206  if (region == NULL) {
207  return;
208  }
209 
210  FREE_AND_NULL_PTR(region->name);
212  FREE_AND_NULL_PTR(region->longname);
213  FREE_AND_NULL_PTR(region->map_first);
214  FREE_AND_NULL_PTR(region->map_bg);
215  FREE_AND_NULL_PTR(region->msg);
216  FREE_AND_NULL_PTR(region->jailmap);
217  efree(region);
218 }
219 
225 static void region_add(region_struct *region)
226 {
227  region_struct *tmp;
228 
229  for (tmp = first_region;
230  tmp != NULL && tmp->next != NULL;
231  tmp = tmp->next) {
232  }
233 
234  if (tmp == NULL) {
235  first_region = region;
236  } else {
237  tmp->next = region;
238  }
239 }
240 
244 static void region_assign_parents(void)
245 {
246  region_struct *region;
247 
248  for (region = first_region; region != NULL; region = region->next) {
249  if (region->parent_name != NULL) {
250  region->parent = region_find_by_name(region->parent_name);
251  }
252  }
253 }
254 
264 region_struct *region_find_by_name(const char *region_name)
265 {
266  region_struct *region;
267 
268  for (region = first_region; region != NULL; region = region->next) {
269  if (strcmp(region->name, region_name) == 0) {
270  return region;
271  }
272  }
273 
274  LOG(BUG, "Got no region for region %s.", region_name);
275  return NULL;
276 }
277 
286 {
287  HARD_ASSERT(region != NULL);
288 
289  for ( ; region != NULL; region = region->parent) {
290  if (region->map_first != NULL) {
291  break;
292  }
293  }
294 
295  return region;
296 }
297 
309 const char *region_get_longname(const region_struct *region)
310 {
311  if (region->longname) {
312  return region->longname;
313  } else if (region->parent) {
314  return region_get_longname(region->parent);
315  }
316 
317  LOG(BUG, "Region %s has no parent and no longname.",
318  region->name);
319  return "no region name";
320 }
321 
330 const char *region_get_msg(const region_struct *region)
331 {
332  if (region->msg) {
333  return region->msg;
334  } else if (region->parent) {
335  return region_get_msg(region->parent);
336  }
337 
338  LOG(BUG, "Region %s has no parent and no msg.",
339  region->name);
340  return "no region message";
341 }
342 
350 int region_enter_jail(object *op)
351 {
352  region_struct *region;
353  mapstruct *m;
354 
355  if (op->map->region == NULL) {
356  return 0;
357  }
358 
359  for (region = op->map->region; region != NULL; region = region->parent) {
360  if (region->jailmap == NULL) {
361  continue;
362  }
363 
364  m = ready_map_name(region->jailmap, NULL, 0);
365 
366  if (m == NULL) {
367  LOG(BUG, "Could not load map '%s' (%d,%d).",
368  region->jailmap, region->jailx, region->jaily);
369  return 0;
370  }
371 
372  return object_enter_map(op,
373  NULL,
374  m,
375  region->jailx,
376  region->jaily,
377  true);
378  }
379 
380  LOG(BUG, "No suitable jailmap for region %s was found.",
381  op->map->region->name);
382  return 0;
383 }
char * parent_name
Definition: map.h:472
char * msg
Definition: map.h:481
#define FREE_AND_NULL_PTR(_xyz_)
Definition: global.h:303
struct region_struct * next
Definition: map.h:453
char * map_bg
Definition: map.h:490
const char * region_get_msg(const region_struct *region)
Definition: region.c:330
void regions_free(void)
Definition: region.c:179
region_struct * region_find_by_name(const char *region_name)
Definition: region.c:264
region_struct * first_region
Definition: region.c:37
bool object_enter_map(object *op, object *exit, mapstruct *m, int x, int y, bool fixed_pos)
Definition: object.c:2956
const char * region_get_longname(const region_struct *region)
Definition: region.c:309
char * jailmap
Definition: map.h:484
int16_t jailx
Definition: map.h:493
static void region_assign_parents(void)
Definition: region.c:244
struct region_struct * parent
Definition: map.h:460
struct sound_ambient_match * next
Next match rule in a linked list.
Definition: sound_ambient.c:39
struct mapdef * map
Definition: object.h:139
int16_t jaily
Definition: map.h:496
bool child_maps
If true, map of this region has all the children.
Definition: map.h:498
char * map_first
Definition: map.h:487
static region_struct * region_get(void)
Definition: region.c:194
void regions_init(void)
Definition: region.c:47
static void region_add(region_struct *region)
Definition: region.c:225
char mapspath[MAX_BUF]
Definition: global.h:348
struct settings_struct settings
Definition: init.c:55
char * longname
Definition: map.h:478
int region_enter_jail(object *op)
Definition: region.c:350
region_struct * region
Definition: map.h:580
char * name
Definition: map.h:463
const region_struct * region_find_with_map(const region_struct *region)
Definition: region.c:285
static void region_free(region_struct *region)
Definition: region.c:204
mapstruct * ready_map_name(const char *name, mapstruct *originator, int flags)
Definition: map.c:1584
Definition: map.h:536