Atrinik Server  4.0
arch.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 
30 #ifndef __CPROTO__
31 
32 #include <global.h>
33 #include <arch.h>
34 #include <artifact.h>
35 #include <loader.h>
36 #include <toolkit/string.h>
37 
46 
50 bool arch_in_init = false;
51 
58 static object *clone_op;
59 
63 static const char *const arch_names[ARCH_MAX] = {
64  "waypoint", "empty_archetype", "base_info", "level_up", "ring_normal",
65  "ring_generic", "amulet_normal", "amulet_generic", "inv_group_next",
66  "inv_group_prev", "inv_start", "inv_end"
67 };
68 
69 /* Prototypes */
70 static void arch_free(archetype_t *at);
71 static void arch_load(void);
72 
78 void arch_init(void)
79 {
80  HARD_ASSERT(arch_table == NULL);
81 
82  clone_op = object_get();
83  arch_in_init = true;
84  arch_load();
85  arch_in_init = false;
86  object_destroy(clone_op);
87 
88  for (int i = 0; i < ARCH_MAX; i++) {
89  arches[i] = arch_find(arch_names[i]);
90 
91  if (arches[i] == NULL) {
92  LOG(ERROR, "Could not find required archetype %s.", arch_names[i]);
93  exit(1);
94  }
95  }
96 }
97 
104 void arch_deinit(void)
105 {
106  archetype_t *at, *tmp, *tail, *tail_tmp;
107  HASH_ITER(hh, arch_table, at, tmp) {
108  HASH_DEL(arch_table, at);
109 
110  for (tail = at; tail != NULL; tail = tail_tmp) {
111  tail_tmp = tail->more;
112  arch_free(tail);
113  }
114  }
115 }
116 
122 static archetype_t *arch_new(void)
123 {
124  HARD_ASSERT(arch_in_init == true);
125 
126  archetype_t *new = ecalloc(1, sizeof(*new));
127  memcpy(&new->clone, clone_op, sizeof(new->clone));
128 
129  return new;
130 }
131 
137 static void arch_free(archetype_t *at)
138 {
139  HARD_ASSERT(at != NULL);
140 
151  efree(at);
152 }
153 
161 static void arch_pass_first(FILE *fp)
162 {
163  HARD_ASSERT(fp != NULL);
164 
165  archetype_t *at = arch_new();
166  at->clone.arch = at;
167 
168  void *buffer = create_loader_buffer(fp);
169  archetype_t *prev = NULL, *last_more = NULL;
170 
171  for (int rc = load_object_fp(fp, &at->clone, MAP_STYLE);
172  rc != LL_EOF;
173  rc = load_object_buffer(buffer, &at->clone, MAP_STYLE)) {
174  switch (rc) {
175  /* A new archetype, add it to the arch table. */
176  case LL_NORMAL:
177  arch_add(at);
178  prev = last_more = at;
179  break;
180 
181  /* Another part of the previous archetype, link it correctly. */
182  case LL_MORE:
183  at->head = prev;
184  at->clone.head = &prev->clone;
185 
186  if (last_more != NULL) {
187  last_more->more = at;
188  last_more->clone.more = &at->clone;
189  }
190 
191  last_more = at;
192  break;
193  }
194 
195  at = arch_new();
196  at->clone.arch = at;
197  }
198 
199  delete_loader_buffer(buffer);
200  efree(at);
201 }
202 
211 static void arch_pass_second(FILE *fp, const char *filename)
212 {
213  char buf[HUGE_BUF];
214  uint64_t linenum = 0;
215  const char *key = NULL, *value = NULL, *error_str = NULL;
216  archetype_t *at = NULL;
217  bool is_more = false;
218 
219  while (fgets(VS(buf), fp) != NULL) {
220  linenum++;
221 
222  char *cp = buf;
223  string_skip_whitespace(cp);
224  string_strip_newline(cp);
225 
226  char *cps[2];
227  if (string_split(cp, cps, arraysize(cps), ' ') < 1) {
228  continue;
229  }
230 
231  key = cps[0];
232  value = cps[1];
233 
234  if (is_more) {
235  if (strcmp(key, "end") == 0) {
236  is_more = false;
237  }
238  } else if (strcmp(key, "Object") == 0) {
239  at = arch_find(value);
240 
241  if (at == NULL) {
242  error_str = "failed to find arch";
243  goto error;
244  }
245  } else if (strcmp(key, "More") == 0) {
246  is_more = true;
247  } else if (at == NULL) {
248  error_str = "expected Object attribute";
249  goto error;
250  } else if (strcmp(key, "end") == 0) {
251  at = NULL;
252  } else if (strcmp(key, "other_arch") == 0) {
253  if (at->clone.other_arch == NULL) {
254  archetype_t *other = arch_find(value);
255  if (other == NULL) {
256  error_str = "failed to find other_arch";
257  goto error;
258  }
259  at->clone.other_arch = other;
260  }
261  } else if (strcmp(key, "randomitems") == 0) {
262  treasure_list_t *tl = treasure_list_find(value);
263  if (tl == NULL) {
264  error_str = "failed to find treasure list";
265  goto error;
266  }
267  at->clone.randomitems = tl;
268  } else if (strcmp(key, "arch") == 0) {
269  object *inv = arch_get(value);
270  load_object_fp(fp, inv, 0);
271  object_insert_into(inv, &at->clone, 0);
272  }
273  }
274 
275  char filename2[MAX_BUF];
276  snprintf(VS(filename2), "%s/artifacts", settings.libpath);
277  fp = fopen(filename2, "rb");
278 
279  if (fp == NULL) {
280  LOG(ERROR, "Can't open %s: %s (%d)", filename2, strerror(errno), errno);
281  exit(1);
282  }
283 
284  linenum = 0;
285  filename = filename2;
286 
287  while (fgets(VS(buf), fp) != NULL) {
288  linenum++;
289 
290  char *cp = buf;
291  string_skip_whitespace(cp);
292  string_strip_newline(cp);
293 
294  char *cps[2];
295  if (string_split(cp, cps, arraysize(cps), ' ') < 1) {
296  continue;
297  }
298 
299  key = cps[0];
300  value = cps[1];
301 
302  if (strcmp(key, "artifact") == 0) {
303  at = arch_find(value);
304  if (at == NULL) {
305  error_str = "failed to find artifact";
306  goto error;
307  }
308  } else if (at == NULL) {
309  // Ignore
310  } else if (strcmp(key, "end") == 0) {
311  at = NULL;
312  } else if (strcmp(key, "def_arch") == 0) {
313  archetype_t *other = arch_find(value);
314  if (other == NULL) {
315  error_str = "failed to find def_arch";
316  goto error;
317  }
318  at->clone.other_arch = other->clone.other_arch;
319  at->clone.randomitems = other->clone.randomitems;
320  } else if (strcmp(key, "other_arch") == 0) {
321  archetype_t *other = arch_find(value);
322  if (other == NULL) {
323  error_str = "failed to find other_arch";
324  goto error;
325  }
326  at->clone.other_arch = other;
327  } else if (strcmp(key, "randomitems") == 0) {
328  treasure_list_t *tl = treasure_list_find(value);
329  if (tl == NULL) {
330  error_str = "failed to find treasure list";
331  goto error;
332  }
333  at->clone.randomitems = tl;
334  }
335  }
336 
337  fclose(fp);
338  return;
339 
340 error:
341  LOG(ERROR, "Error parsing %s, line %" PRIu64 ", %s: %s %s", filename,
342  linenum, error_str != NULL ? error_str : "", key != NULL ? key : "",
343  value != NULL ? value : "");
344  exit(1);
345 }
346 
354 static void arch_load(void)
355 {
356  TIMER_START(1);
357 
358  char filename[MAX_BUF];
359  snprintf(VS(filename), "%s/archetypes", settings.libpath);
360  FILE *fp = fopen(filename, "rb");
361 
362  if (fp == NULL) {
363  LOG(ERROR, "Can't open archetype file %s: %s (%d)", filename,
364  strerror(errno), errno);
365  exit(1);
366  }
367 
368  arch_pass_first(fp);
369  rewind(fp);
370 
371  /* If not called before, reads all artifacts from file */
372  artifact_init();
373  treasure_init();
374 
375  arch_pass_second(fp, filename);
376  fclose(fp);
377 
378  TIMER_UPDATE(1);
379  LOG(DEVEL, "Archetype loading took %f seconds", TIMER_GET(1));
380 }
381 
391 {
392  HARD_ASSERT(at != NULL);
393  HARD_ASSERT(arch_in_init == true);
394 
395  SOFT_ASSERT(at->name != NULL, "Archetype has no name.");
396 
397  HASH_ADD_KEYPTR(hh, arch_table, at->name, strlen(at->name), at);
398 }
399 
407 archetype_t *arch_find(const char *name)
408 {
409  if (name == NULL) {
410  return NULL;
411  }
412 
413  archetype_t *at;
414  HASH_FIND_STR(arch_table, name, at);
415  return at;
416 }
417 
430 object *arch_get(const char *name)
431 {
432  archetype_t *at = arch_find(name);
433  if (at == NULL) {
434  return object_create_singularity(name);
435  }
436  return arch_to_object(at);
437 }
438 
447 {
448  HARD_ASSERT(at != NULL);
449 
450  object *op = object_get();
451  object_copy_full(op, &at->clone);
452  op->arch = at;
453  return op;
454 }
455 
465 {
466  HARD_ASSERT(at != NULL);
467  HARD_ASSERT(arch_in_init == true);
468 
469  archetype_t *new = ecalloc(1, sizeof(*new));
470  memcpy(&new->clone, &at->clone, sizeof(new->clone));
471  ADD_REF_NOT_NULL_HASH(new->clone.name);
472  ADD_REF_NOT_NULL_HASH(new->clone.title);
473  ADD_REF_NOT_NULL_HASH(new->clone.race);
474  ADD_REF_NOT_NULL_HASH(new->clone.slaying);
475  ADD_REF_NOT_NULL_HASH(new->clone.msg);
476  new->clone.arch = new;
477  return new;
478 }
479 
480 #endif
archetype_t * arch_table
Definition: arch.c:41
void object_destroy(object *ob)
Definition: object.c:1441
static void arch_load(void)
Definition: arch.c:354
void arch_deinit(void)
Definition: arch.c:104
void arch_init(void)
Definition: arch.c:78
void object_free_key_values(object *op)
Definition: object.c:2456
const char * race
Definition: object.h:174
object * object_get(void)
Definition: object.c:993
#define LL_NORMAL
Object was successfully loaded.
Definition: loader.h:40
struct treasure_list * randomitems
Definition: object.h:231
object * object_create_singularity(const char *name)
Definition: object.c:3281
const char * slaying
Definition: object.h:180
static archetype_t * arch_new(void)
Definition: arch.c:122
struct archetype * arch
Definition: object.h:225
struct archetype * other_arch
Definition: object.h:228
char libpath[MAX_BUF]
Definition: global.h:338
void object_destroy_inv(object *ob)
Definition: object.c:1414
const char * title
Definition: object.h:171
#define LL_MORE
Object has more parts that need loading.
Definition: loader.h:39
archetype_t * arches[ARCH_MAX]
Definition: arch.c:45
static void arch_pass_first(FILE *fp)
Definition: arch.c:161
Definition: arch.h:40
object * arch_get(const char *name)
Definition: arch.c:430
archetype_t * arch_clone(archetype_t *at)
Definition: arch.c:464
struct archetype * more
Next part of a linked object.
Definition: arch.h:42
object * object_insert_into(object *op, object *where, int flag)
Definition: object.c:2158
static object * clone_op
Definition: arch.c:58
static void arch_free(archetype_t *at)
Definition: arch.c:137
int load_object_fp(FILE *fp, object *op, int map_flags)
Definition: object.c:48576
#define LL_EOF
End of file reached.
Definition: loader.h:38
const char * name
Definition: object.h:168
void arch_add(archetype_t *at)
Definition: arch.c:390
static const char *const arch_names[ARCH_MAX]
Definition: arch.c:63
#define ADD_REF_NOT_NULL_HASH(_nv_)
Definition: global.h:153
archetype_t * arch_find(const char *name)
Definition: arch.c:407
void artifact_init(void)
Definition: artifact.c:51
struct settings_struct settings
Definition: init.c:55
shstr * name
More definite name, like "kobold".
Definition: arch.h:46
Maximum number of cached archetype pointers.
Definition: arch.h:68
const char * msg
Definition: object.h:183
#define FREE_AND_CLEAR_HASH(_nv_)
Definition: global.h:130
object * arch_to_object(archetype_t *at)
Definition: arch.c:446
struct obj * head
Definition: object.h:136
treasure_list_t * treasure_list_find(const char *name)
Definition: treasure.c:789
shstr * custom_name
Definition: object.h:190
void treasure_init(void)
Definition: treasure.c:754
bool arch_in_init
Definition: arch.c:50
struct archetype * head
The main part of a linked object.
Definition: arch.h:41
#define MAP_STYLE
Definition: map.h:153
void object_copy_full(object *op, const object *src)
Definition: object.c:970
struct obj * more
Definition: object.h:133
object clone
An object from which to do object_copy().
Definition: arch.h:47
int load_object_buffer(void *buffer, object *op, int map_flags)
Definition: object.c:48633
shstr * glow
Definition: object.h:193
static void arch_pass_second(FILE *fp, const char *filename)
Definition: arch.c:211