Crossfire Server, Trunk  R20911
server.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
19 #include "global.h"
20 
21 #include <assert.h>
22 #include <ctype.h>
23 #include <fcntl.h>
24 #include <math.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <time.h>
28 
29 #ifndef WIN32
30 #include <unistd.h>
31 #endif
32 
33 /* FIXME: This is required on certain systems to get crypt(3) to work. */
34 #ifdef HAVE_CRYPT_H
35 #include <crypt.h>
36 #endif
37 
38 #include "object.h"
39 #include "path.h"
40 #include "random_maps/random_map.h"
41 #include "random_maps/rproto.h"
42 #include "sproto.h"
43 #include "tod.h"
44 #include "version.h"
45 
47 static const char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
48 
64 static char const* crypt_string(char const str[static 1], char const* salt) {
65 #if defined(WIN32) || (defined(__FreeBSD__))
66  // Legacy configuration: use crypt everywhere but on Windows and FreeBSD
67  if (settings.crypt_mode == 0) {
68  return str;
69  }
70 #endif
71  char s[3];
72 
73  if (salt == NULL) {
74  /* Generate a two-character salt for the DES cipher.
75  * We want the salt to be in this character set.
76  */
77  static const char *const c =
78  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
79  s[0] = c[RANDOM()%(int)strlen(c)],
80  s[1] = c[RANDOM()%(int)strlen(c)];
81  } else {
82  s[0] = salt[0],
83  s[1] = salt[1];
84  }
85  s[2] = '\0';
86 
87  return crypt(str, s);
88 }
89 
90 char const* newhash(char const password[static 1]) {
91  return crypt_string(password, NULL);
92 }
93 
103 bool check_password(const char *typed, const char *crypted) {
104  // An empty hashed password only matches an empty input password.
105  if (strlen(crypted) == 0) {
106  return strlen(typed) == 0 ? true : false;
107  }
108 
109  return strcmp(crypt_string(typed, crypted), crypted) == 0;
110 }
111 
121 void enter_player_savebed(object *op) {
122  mapstruct *oldmap = op->map;
123  object *tmp;
124 
125  tmp = object_new();
126 
127  EXIT_PATH(tmp) = add_string(op->contr->savebed_map);
128  EXIT_X(tmp) = op->contr->bed_x;
129  EXIT_Y(tmp) = op->contr->bed_y;
130  enter_exit(op, tmp);
131  /* If the player has not changed maps and the name does not match
132  * that of the savebed, his savebed map is gone. Lets go back
133  * to the emergency path. Update what the players savebed is
134  * while we're at it.
135  */
136  if (oldmap == op->map && strcmp(op->contr->savebed_map, oldmap->path)) {
137  LOG(llevDebug, "Player %s savebed location %s is invalid - going to emergency location (%s)\n",
143  EXIT_PATH(tmp) = add_string(op->contr->savebed_map);
144  EXIT_X(tmp) = op->contr->bed_x;
145  EXIT_Y(tmp) = op->contr->bed_y;
146  enter_exit(op, tmp);
147  }
149 }
150 
162 static void enter_map(object *op, mapstruct *newmap, int x, int y) {
163  mapstruct *oldmap = op->map;
164 
165  if (out_of_map(newmap, x, y)) {
166  LOG(llevError, "enter_map: supplied coordinates are not within the map! (%s: %d, %d)\n", newmap->path, x, y);
167  /* If op has invalid (probably -1,-1) coordinates, force them to a correct value, else issues later on. */
168  if (op->x == x)
169  op->x = MAP_ENTER_X(newmap);
170  if (op->y == y)
171  op->y = MAP_ENTER_Y(newmap);
172  x = MAP_ENTER_X(newmap);
173  y = MAP_ENTER_Y(newmap);
174  if (out_of_map(newmap, x, y)) {
175  LOG(llevError, "enter_map: map %s provides invalid default enter location (%d, %d) > (%d, %d)\n", newmap->path, x, y, MAP_WIDTH(newmap), MAP_HEIGHT(newmap));
177  "The exit is closed");
178  return;
179  }
180  }
181  /* try to find a spot for the player */
182  if (ob_blocked(op, newmap, x, y)) { /* First choice blocked */
183  /* We try to find a spot for the player, starting closest in.
184  * We could use object_find_first_free_spot(), but that doesn't randomize it at all,
185  * So for example, if the north space is free, you would always end up there even
186  * if other spaces around are available.
187  * Note that for the second and third calls, we could start at a position other
188  * than one, but then we could end up on the other side of walls and so forth.
189  */
190  int i = object_find_free_spot(op, newmap, x, y, 1, SIZEOFFREE1+1);
191  if (i == -1) {
192  i = object_find_free_spot(op, newmap, x, y, 1, SIZEOFFREE2+1);
193  if (i == -1)
194  i = object_find_free_spot(op, newmap, x, y, 1, SIZEOFFREE);
195  }
196  if (i != -1) {
197  x += freearr_x[i];
198  y += freearr_y[i];
199  } else {
200  /* not much we can do in this case. */
201  LOG(llevInfo, "enter_map: Could not find free spot for player - will dump on top of object (%s: %d, %d)\n", newmap->path, x, y);
202  }
203  } /* end if looking for free spot */
204 
205  /* If it is a player login, he has yet to be inserted anyplace.
206  * otherwise, we need to deal with removing the playe here.
207  */
208  if (!QUERY_FLAG(op, FLAG_REMOVED))
209  object_remove(op);
210  if (op->map != NULL) {
211  /* Lauwenmark : Here we handle the MAPLEAVE global event */
213  }
214  /* object_remove clears these so they must be reset after the object_remove() call */
215  object_insert_in_map_at(op, newmap, NULL, INS_NO_WALK_ON, x, y);
216 
217  /* Lauwenmark : Here we handle the MAPENTER global event */
219 
220  newmap->timeout = 0;
221  object_set_enemy(op, NULL);
222 
223  if (op->contr) {
224  safe_strncpy(op->contr->maplevel, newmap->path,
225  sizeof(op->contr->maplevel));
226  op->contr->count = 0;
227  }
228 
229  /* Update any golems */
230  if (op->type == PLAYER && op->contr->ranges[range_golem] != NULL) {
231  int i = object_find_free_spot(op->contr->ranges[range_golem], newmap, x, y, 1, SIZEOFFREE);
233  if (i == -1) {
236  op->contr->ranges[range_golem] = NULL;
237  op->contr->golem_count = 0;
238  } else {
239  object_insert_in_map_at(op->contr->ranges[range_golem], newmap, NULL, 0, x+freearr_x[i], y+freearr_y[i]);
241  }
242  }
243  op->direction = 0;
244 
245  /* since the players map is already loaded, we don't need to worry
246  * about pending objects.
247  */
248  pets_remove_all();
249 
250  /* If the player is changing maps, we need to do some special things
251  * Do this after the player is on the new map - otherwise the force swap of the
252  * old map does not work.
253  */
254  if (oldmap != newmap) {
255  if (oldmap) { /* adjust old map */
256  if (oldmap->players <= 0) /* can be less than zero due to errors in tracking this */
257  set_map_timeout(oldmap);
258  }
259  }
260  swap_below_max(newmap->path);
261 
262  if (op->type == PLAYER) {
263  map_newmap_cmd(&op->contr->socket);
265  }
266 }
267 
274 void set_map_timeout(mapstruct *oldmap) {
275 #if MAP_MAXTIMEOUT
276  oldmap->timeout = MAP_TIMEOUT(oldmap);
277  /* Do MINTIMEOUT first, so that MAXTIMEOUT is used if that is
278  * lower than the min value.
279  */
280 #if MAP_MINTIMEOUT
281  if (oldmap->timeout < MAP_MINTIMEOUT) {
282  oldmap->timeout = MAP_MINTIMEOUT;
283  }
284 #endif
285  if (oldmap->timeout > MAP_MAXTIMEOUT) {
286  oldmap->timeout = MAP_MAXTIMEOUT;
287  }
288 #else
289  /* save out the map */
290  swap_map(oldmap);
291 #endif /* MAP_MAXTIMEOUT */
292 }
293 
307 static char *clean_path(const char *file, char *newpath, int size) {
308  char *cp;
309 
310  snprintf(newpath, size, "%s", file);
311  for (cp = newpath; *cp != '\0'; cp++) {
312  if (*cp == '/')
313  *cp = '_';
314  }
315  return newpath;
316 }
317 
335 static char *unclean_path(const char *src, char *newpath, int size) {
336  char *cp;
337 
338  cp = strrchr(src, '/');
339  if (cp)
340  snprintf(newpath, size, "%s", cp+1);
341  else
342  snprintf(newpath, size, "%s", src);
343 
344  for (cp = newpath; *cp != '\0'; cp++) {
345  if (*cp == '_')
346  *cp = '/';
347  }
348  return newpath;
349 }
350 
351 
361 static void enter_random_map(object *pl, object *exit_ob) {
362  mapstruct *new_map;
363  char newmap_name[HUGE_BUF], buf[HUGE_BUF], *cp;
364  static int reference_number = 0;
365  RMParms rp;
366 
367  memset(&rp, 0, sizeof(RMParms));
368  rp.Xsize = -1;
369  rp.Ysize = -1;
370  rp.region = get_region_by_map(exit_ob->map);
371  if (exit_ob->msg)
372  set_random_map_variable(&rp, exit_ob->msg);
373  rp.origin_x = exit_ob->x;
374  rp.origin_y = exit_ob->y;
375  safe_strncpy(rp.origin_map, pl->map->path, sizeof(rp.origin_map));
376 
377  /* If we have a final_map, use it as a base name to give some clue
378  * as where the player is. Otherwise, use the origin map.
379  * Take the last component (after the last slash) to give
380  * shorter names without bogus slashes.
381  */
382  if (rp.final_map[0]) {
383  cp = strrchr(rp.final_map, '/');
384  if (!cp)
385  cp = rp.final_map;
386  } else {
387  cp = strrchr(rp.origin_map, '/');
388  if (!cp)
389  cp = rp.origin_map;
390  /* Need to strip of any trailing digits, if it has them */
391  snprintf(buf, sizeof(buf), "%s", cp);
392  while (isdigit(buf[strlen(buf)-1]))
393  buf[strlen(buf)-1] = 0;
394  cp = buf;
395  }
396 
397  snprintf(newmap_name, sizeof(newmap_name), "/random/%s%04d", cp+1, reference_number++);
398 
399  /* now to generate the actual map. */
400  new_map = generate_random_map(newmap_name, &rp, NULL);
401 
402  /* Update the exit_ob so it now points directly at the newly created
403  * random maps. Not that it is likely to happen, but it does mean that a
404  * exit in a unique map leading to a random map will not work properly.
405  * It also means that if the created random map gets reset before
406  * the exit leading to it, that the exit will no longer work.
407  */
408  if (new_map) {
409  int x, y;
410 
411  x = EXIT_X(exit_ob) = MAP_ENTER_X(new_map);
412  y = EXIT_Y(exit_ob) = MAP_ENTER_Y(new_map);
413  EXIT_PATH(exit_ob) = add_string(newmap_name);
414  snprintf(new_map->path, sizeof(new_map->path), "%s", newmap_name);
415  enter_map(pl, new_map, x, y);
416  }
417 }
418 
428 static void enter_fixed_template_map(object *pl, object *exit_ob) {
429  mapstruct *new_map;
430  char tmpnum[32], exitpath[HUGE_BUF], resultname[HUGE_BUF], tmpstring[HUGE_BUF], *sourcemap;
431  char new_map_name[MAX_BUF];
432 
433  /* Split the exit path string into two parts, one
434  * for where to store the map, and one for were
435  * to generate the map from.
436  */
437  snprintf(exitpath, sizeof(exitpath), "%s", EXIT_PATH(exit_ob)+2);
438  sourcemap = strchr(exitpath, '!');
439  if (!sourcemap) {
442  "The %s is closed.",
443  exit_ob->name);
444  /* Should only occur when no source map is set.
445  */
446  LOG(llevError, "enter_fixed_template_map: Exit %s (%d,%d) on map %s has no source template.\n", exit_ob->name, exit_ob->x, exit_ob->y, exit_ob->map->path);
447  return;
448  }
449  *sourcemap++ = '\0';
450 
451  /* If we are not coming from a template map, we can use relative directories
452  * for the map to generate from.
453  */
454  if (!exit_ob->map->is_template) {
455  /* We can't use exitpath directly, as sourcemap points there. */
456  path_combine_and_normalize(exit_ob->map->path, sourcemap, tmpstring, sizeof(tmpstring));
457  snprintf(exitpath, sizeof(exitpath), "%s", tmpstring);
458  sourcemap = exitpath;
459  }
460 
461  /* Do replacement of %x, %y, and %n to the x coord of the exit, the y coord
462  * of the exit, and the name of the map the exit is on, respectively.
463  */
464  snprintf(tmpnum, sizeof(tmpnum), "%d", exit_ob->x);
465  replace(exitpath, "%x", tmpnum, resultname, sizeof(resultname));
466 
467  snprintf(tmpnum, sizeof(tmpnum), "%d", exit_ob->y);
468  snprintf(tmpstring, sizeof(tmpstring), "%s", resultname);
469  replace(tmpstring, "%y", tmpnum, resultname, sizeof(resultname));
470 
471  snprintf(tmpstring, sizeof(tmpstring), "%s", resultname);
472  replace(tmpstring, "%n", exit_ob->map->name, resultname, sizeof(resultname));
473 
474  /* If we are coming from another template map, use reletive paths unless
475  * indicated otherwise.
476  */
477  if (exit_ob->map->is_template && (resultname[0] != '/')) {
478  path_combine_and_normalize(exit_ob->map->path, resultname, new_map_name, sizeof(new_map_name));
479  } else {
480  create_template_pathname(resultname, new_map_name, sizeof(new_map_name));
481  }
482 
483  /* Attempt to load the map, if unable to, then
484  * create the map from the template.
485  */
486  new_map = ready_map_name(new_map_name, MAP_PLAYER_UNIQUE);
487  if (!new_map) {
488  char path[MAX_BUF];
489 
490  create_pathname(sourcemap, path, MAX_BUF);
491  new_map = mapfile_load(path, MAP_PLAYER_UNIQUE);
492  }
493 
494  if (new_map) {
495  /* set the path of the map to where it should be
496  * so we don't just save over the source map.
497  */
498  snprintf(new_map->path, sizeof(new_map->path), "%s", new_map_name);
499  new_map->is_template = 1;
500  enter_map(pl, new_map, EXIT_X(exit_ob), EXIT_Y(exit_ob));
501  } else {
504  "The %s is closed.",
505  exit_ob->name);
506  /* Should only occur when an invalid source map is set.
507  */
508  LOG(llevDebug, "enter_fixed_template_map: Exit %s (%d,%d) on map %s leads no where.\n", exit_ob->name, exit_ob->x, exit_ob->y, exit_ob->map->path);
509  }
510 }
511 
521 static void enter_random_template_map(object *pl, object *exit_ob) {
522  mapstruct *new_map;
523  char tmpnum[32], resultname[HUGE_BUF], tmpstring[HUGE_BUF];
524  char new_map_name[MAX_BUF];
525  RMParms rp;
526 
527  /* Do replacement of %x, %y, and %n to the x coord of the exit, the y coord
528  * of the exit, and the name of the map the exit is on, respectively.
529  */
530  snprintf(tmpnum, sizeof(tmpnum), "%d", exit_ob->x);
531  replace(EXIT_PATH(exit_ob)+3, "%x", tmpnum, resultname, sizeof(resultname));
532 
533  snprintf(tmpnum, sizeof(tmpnum), "%d", exit_ob->y);
534  snprintf(tmpstring, sizeof(tmpstring), "%s", resultname);
535  replace(tmpstring, "%y", tmpnum, resultname, sizeof(resultname));
536 
537  snprintf(tmpstring, sizeof(tmpstring), "%s", resultname);
538  replace(tmpstring, "%n", exit_ob->map->name, resultname, sizeof(resultname));
539 
540  /* If we are coming from another template map, use reletive paths unless
541  * indicated otherwise.
542  */
543  if (exit_ob->map->is_template && (resultname[0] != '/')) {
544  path_combine_and_normalize(exit_ob->map->path, resultname, new_map_name, sizeof(new_map_name));
545  } else {
546  create_template_pathname(resultname, new_map_name, sizeof(new_map_name));
547  }
548 
549  new_map = ready_map_name(new_map_name, MAP_PLAYER_UNIQUE);
550  if (!new_map) {
551  memset(&rp, 0, sizeof(RMParms));
552  rp.Xsize = -1;
553  rp.Ysize = -1;
554  rp.region = get_region_by_map(exit_ob->map);
555  if (exit_ob->msg)
556  set_random_map_variable(&rp, exit_ob->msg);
557  rp.origin_x = exit_ob->x;
558  rp.origin_y = exit_ob->y;
559  safe_strncpy(rp.origin_map, pl->map->path, sizeof(rp.origin_map));
560 
561  /* now to generate the actual map. */
562  new_map = generate_random_map(new_map_name, &rp, NULL);
563  }
564 
565  /* Update the exit_ob so it now points directly at the newly created
566  * random maps. Not that it is likely to happen, but it does mean that a
567  * exit in a unique map leading to a random map will not work properly.
568  * It also means that if the created random map gets reset before
569  * the exit leading to it, that the exit will no longer work.
570  */
571  if (new_map) {
572  int x, y;
573 
574  x = EXIT_X(exit_ob) = MAP_ENTER_X(new_map);
575  y = EXIT_Y(exit_ob) = MAP_ENTER_Y(new_map);
576  new_map->is_template = 1;
577  enter_map(pl, new_map, x, y);
578  }
579 }
580 
589 static void enter_unique_map(object *op, object *exit_ob) {
590  char apartment[HUGE_BUF], path[MAX_BUF];
591  mapstruct *newmap;
592 
593  if (EXIT_PATH(exit_ob)[0] == '/') {
594  snprintf(apartment, sizeof(apartment), "%s/%s/%s/%s", settings.localdir, settings.playerdir, op->name, clean_path(EXIT_PATH(exit_ob), path, sizeof(path)));
595  newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE);
596  if (!newmap) {
597  create_pathname(EXIT_PATH(exit_ob), path, sizeof(path));
598  newmap = mapfile_load(path, MAP_PLAYER_UNIQUE);
599  }
600  } else { /* relative directory */
601  char reldir[HUGE_BUF], tmpc[HUGE_BUF], *cp;
602 
603  if (exit_ob->map->unique) {
604  unclean_path(exit_ob->map->path, reldir, sizeof(reldir));
605 
606  /* Need to copy this over, as clean_path only has one static return buffer */
607  clean_path(reldir, tmpc, sizeof(tmpc));
608  /* Remove final component, if any */
609  if ((cp = strrchr(tmpc, '_')) != NULL)
610  *cp = 0;
611 
612  snprintf(apartment, sizeof(apartment), "%s/%s/%s/%s_%s", settings.localdir, settings.playerdir, op->name, tmpc, clean_path(EXIT_PATH(exit_ob), path, sizeof(path)));
613 
614  newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE);
615  if (!newmap) {
616  create_pathname(path_combine_and_normalize(reldir, EXIT_PATH(exit_ob), tmpc, sizeof(tmpc)), path, sizeof(path));
617  newmap = mapfile_load(path, MAP_PLAYER_UNIQUE);
618  }
619  } else {
620  /* The exit is unique, but the map we are coming from is not unique. So
621  * use the basic logic - don't need to demangle the path name
622  */
623  path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob), reldir, sizeof(reldir));
624  snprintf(apartment, sizeof(apartment), "%s/%s/%s/%s", settings.localdir, settings.playerdir, op->name, clean_path(reldir, path, sizeof(path)));
625  newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE);
626  if (!newmap) {
627  path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob), reldir, sizeof(reldir));
628  newmap = ready_map_name(reldir, 0);
629  if (newmap)
630  apply_auto_fix(newmap);
631  }
632  }
633  }
634 
635  if (newmap) {
636  snprintf(newmap->path, sizeof(newmap->path), "%s", apartment);
637  newmap->unique = 1;
638  enter_map(op, newmap, EXIT_X(exit_ob), EXIT_Y(exit_ob));
639  } else {
642  "The %s is closed.",
643  exit_ob->name);
644  /* Perhaps not critical, but I would think that the unique maps
645  * should be new enough this does not happen. This also creates
646  * a strange situation where some players could perhaps have visited
647  * such a map before it was removed, so they have the private
648  * map, but other players can't get it anymore.
649  */
650  LOG(llevDebug, "enter_unique_map: Exit %s (%d,%d) on map %s is leads no where.\n", exit_ob->name, exit_ob->x, exit_ob->y, exit_ob->map->path);
651  }
652 }
653 
654 void enter_player_maplevel(object *op) {
655  int flags = 0, x = op->x, y = op->y;
656  mapstruct *newmap;
657 
658  assert(op != NULL);
659  assert(op->type == PLAYER);
660 
661  /* Hypothetically, I guess its possible that a standard map matches
662  * the localdir, but that seems pretty unlikely - unlikely enough that
663  * I'm not going to attempt to try to deal with that possibility.
664  * We use the fact that when a player saves on a unique map, it prepends
665  * the localdir to that name. So its an easy way to see of the map is
666  * unique or not.
667  */
668  if (!strncmp(op->contr->maplevel, settings.localdir, strlen(settings.localdir)))
669  flags = MAP_PLAYER_UNIQUE;
670 
671  /* newmap returns the map (if already loaded), or loads it for us. */
672  newmap = ready_map_name(op->contr->maplevel, flags);
673  if (!newmap) {
675  x = settings.emergency_x;
676  y = settings.emergency_y;
677  if (!newmap) {
678  LOG(llevError, "Fatal: Could not load emergency map!\n");
679  abort();
680  }
681 
683  "You find yourself somewhere unexpected...");
684  }
685 
686  /* as a special case, if coordinates are (-1, -1), then the item should
687  * be put at the default location. Used for loginmethod 0 (old clients). */
688  if (x == -1 && y == -1) {
689  x = MAP_ENTER_X(newmap);
690  y = MAP_ENTER_Y(newmap);
691  }
692 
693  enter_map(op, newmap, x, y);
694 }
695 
709 void enter_exit(object *op, object *exit_ob) {
710 #define PORTAL_DESTINATION_NAME "Town portal destination" /* this one should really be in a header file */
711  /* It may be nice to support other creatures moving across
712  * exits, but right now a lot of the code looks at op->contr,
713  * so thta is an RFE.
714  */
715  if (op->type != PLAYER)
716  return;
717 
718  /* Need to remove player from transport */
719  if (op->contr->transport)
720  ob_apply(op->contr->transport, op, AP_UNAPPLY);
721 
722  assert(exit_ob != NULL);
723  assert(EXIT_PATH(exit_ob) != NULL);
724 
725  /* check to see if we make a template map */
726  if (EXIT_PATH(exit_ob) && EXIT_PATH(exit_ob)[1] == '@') {
727  if (EXIT_PATH(exit_ob)[2] == '!') {
728  /* generate a template map randomly */
729  enter_random_template_map(op, exit_ob);
730  } else {
731  /* generate a template map from a fixed template */
732  enter_fixed_template_map(op, exit_ob);
733  }
734  }
735  /* check to see if we make a randomly generated map */
736  else if (EXIT_PATH(exit_ob) && EXIT_PATH(exit_ob)[1] == '!') {
737  enter_random_map(op, exit_ob);
738  } else if (QUERY_FLAG(exit_ob, FLAG_UNIQUE)) {
739  enter_unique_map(op, exit_ob);
740  } else {
741  int x = EXIT_X(exit_ob), y = EXIT_Y(exit_ob);
742  /* 'Normal' exits that do not do anything special
743  * Simple enough we don't need another routine for it.
744  */
745  mapstruct *newmap;
746  if (exit_ob->map) {
747  char tmp_path[HUGE_BUF];
748 
749  path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob), tmp_path, sizeof(tmp_path));
750  newmap = ready_map_name(tmp_path, 0);
751  /* Random map was previously generated, but is no longer about. Lets generate a new
752  * map.
753  */
754  if (!newmap && !strncmp(EXIT_PATH(exit_ob), "/random/", 8)) {
755  /* Maps that go down have a message set. However, maps that go
756  * up, don't. If the going home has reset, there isn't much
757  * point generating a random map, because it won't match the maps.
758  */
759  if (exit_ob->msg) {
760  enter_random_map(op, exit_ob);
761  } else {
764  "The %s is closed.",
765  exit_ob->name);
766  return;
767  }
768 
769  /* For exits that cause damages (like pits). Don't know if any
770  * random maps use this or not.
771  */
772  if (exit_ob->stats.dam && op->type == PLAYER)
773  hit_player(op, exit_ob->stats.dam, exit_ob, exit_ob->attacktype, 1);
774  return;
775  }
776  } else {
777  /* For word of recall and other force objects
778  * They contain the full pathname of the map to go back to,
779  * so we don't need to normalize it.
780  * But we do need to see if it is unique or not
781  */
782  if (!strncmp(EXIT_PATH(exit_ob), settings.localdir, strlen(settings.localdir)))
783  newmap = ready_map_name(EXIT_PATH(exit_ob), MAP_PLAYER_UNIQUE);
784  else
785  newmap = ready_map_name(EXIT_PATH(exit_ob), 0);
786  }
787  if (!newmap) {
788  if (exit_ob->name)
791  "The %s is closed.",
792  exit_ob->name);
793  /* don't cry to momma if name is not set - as in tmp objects
794  * used by the savebed code and character creation */
795  return;
796  }
797 
798  if (x == -1 && y == -1) {
799  x = MAP_ENTER_X(newmap);
800  y = MAP_ENTER_Y(newmap);
801  }
802 
803  /* mids 02/13/2002 if exit is damned, update players death & WoR home-position and delete town portal */
804  if (QUERY_FLAG(exit_ob, FLAG_DAMNED)) {
805  object *tmp;
806 
807  /* remove an old force with a slaying field == PORTAL_DESTINATION_NAME */
809  if (tmp) {
810  object_remove(tmp);
812  }
813 
814  path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob), op->contr->savebed_map, sizeof(op->contr->savebed_map));
815  op->contr->bed_x = EXIT_X(exit_ob), op->contr->bed_y = EXIT_Y(exit_ob);
816  save_player(op, 1);
817  }
818 
819  enter_map(op, newmap, x, y);
820  }
821 
822  LOG(llevDebug, "%s enters %s\n", op->name, EXIT_PATH(exit_ob));
823 
824  /* For exits that cause damages (like pits) */
825  if (exit_ob->stats.dam && op->type == PLAYER)
826  hit_player(op, exit_ob->stats.dam, exit_ob, exit_ob->attacktype, 1);
827 }
828 
834 static void process_players1(void) {
835  int flag;
836  player *pl, *plnext;
837 
838  /* Basically, we keep looping until all the players have done their actions. */
839  for (flag = 1; flag != 0; ) {
840  flag = 0;
841  for (pl = first_player; pl != NULL; pl = plnext) {
842  plnext = pl->next; /* In case a player exits the game in handle_player() */
843 
844  if (pl->ob == NULL)
845  continue;
846 
847  /* Only do this on the first pass - what we are recording
848  * here is the number of ticks the player has been online - not
849  * how many actions/moves the player has done.
850  */
851  if (!flag) pl->ticks_played++;
852 
854  if (pl->followed_player) {
856  if (followed && followed->ob && followed->ob->map) {
857  rv_vector rv;
858 
859  if (!get_rangevector(pl->ob, followed->ob, &rv, 0) || rv.distance > 4) {
860  int space = object_find_free_spot(pl->ob, followed->ob->map, followed->ob->x, followed->ob->y, 1, 25);
861  if (space == -1)
863  space = 0;
864  object_remove(pl->ob);
865  object_insert_in_map_at(pl->ob, followed->ob->map, NULL, 0, followed->ob->x+freearr_x[space], followed->ob->y+freearr_y[space]);
866  map_newmap_cmd(&pl->socket);
868  }
869  } else {
870  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Player %s left or ambiguous name.", pl->followed_player);
872  }
873  }
875  if (pl->ob->speed_left > 0) {
876  if (handle_newcs_player(pl->ob))
877  flag = 1;
878  } /* end if player has speed left */
879 
880  /* If the player is not actively playing, don't make a
881  * backup save - nothing to save anyway. Plus, the
882  * map may not longer be valid. This can happen when the
883  * player quits - they exist for purposes of tracking on the map,
884  * but don't actually reside on any actual map.
885  */
886  if (QUERY_FLAG(pl->ob, FLAG_REMOVED))
887  continue;
888 
889 #ifdef AUTOSAVE
890  /* check for ST_PLAYING state so that we don't try to save off when
891  * the player is logging in.
892  */
893  if ((pl->last_save_tick+AUTOSAVE) < pticks && pl->state == ST_PLAYING) {
894  /* Don't save the player on unholy ground. Instead, increase the
895  * tick time so it will be about 10 seconds before we try and save
896  * again.
897  */
898  if (get_map_flags(pl->ob->map, NULL, pl->ob->x, pl->ob->y, NULL, NULL)&P_NO_CLERIC) {
899  pl->last_save_tick += 100;
900  } else {
901  save_player(pl->ob, 1);
902  pl->last_save_tick = pticks;
903  hiscore_check(pl->ob, 1);
904  }
905  }
906 #endif
907  } /* end of for loop for all the players */
908  } /* for flag */
909  for (pl = first_player; pl != NULL; pl = pl->next) {
910  int has_action = 1;
911 
912  pl->ob->weapon_speed_left += pl->ob->weapon_speed;
913  if (pl->ob->weapon_speed_left > 1.0)
914  pl->ob->weapon_speed_left = 1.0;
915 
916  pl->socket.sounds_this_tick = 0;
917 
918  if (settings.casting_time == TRUE) {
919  if (pl->ob->casting_time > 0) {
920  pl->ob->casting_time--;
921  has_action = 0;
922  }
923  }
924  /* If the character is idle (standing around resting) increase
925  * regen rates.
926  */
927  if (has_action && pl->ob->speed_left > 0) {
928  pl->ob->last_heal -= 2;
929  pl->ob->last_sp -= 2;
930  pl->ob->last_grace -= 2;
931  pl->ob->last_eat += 2; /* Slow down food consumption */
932  }
933  do_some_living(pl->ob);
934  }
935 }
936 
944 static void process_players2(void) {
945  player *pl;
946 
947  /* Then check if any players should use weapon-speed instead of speed */
948  for (pl = first_player; pl != NULL; pl = pl->next) {
949  /* The code that did weapon_sp handling here was out of place -
950  * this isn't called until after the player has finished there
951  * actions, and is thus out of place. All we do here is bounds
952  * checking.
953  */
954  if (pl->has_hit) {
955  /* This needs to be here - if the player is running, we need to
956  * clear this each tick, but new commands are not being received
957  * so execute_newserver_command() is never called
958  */
959  pl->has_hit = 0;
960  } else if (pl->ob->speed_left > pl->ob->speed)
961  pl->ob->speed_left = pl->ob->speed;
962  }
963 }
964 
965 #define SPEED_DEBUG
966 
970 void process_events(void) {
971  object *op;
972  object marker;
973  tag_t tag;
974 
976 
977  memset(&marker, 0, sizeof(object));
978  /* Put marker object at beginning of active list */
979  marker.active_next = active_objects;
980 
981  if (marker.active_next)
982  marker.active_next->active_prev = &marker;
983  marker.active_prev = NULL;
984  active_objects = &marker;
985 
986  while (marker.active_next) {
987  op = marker.active_next;
988  tag = op->count;
989 
990  /* Move marker forward - swap op and marker */
991  op->active_prev = marker.active_prev;
992 
993  if (op->active_prev)
994  op->active_prev->active_next = op;
995  else
996  active_objects = op;
997 
998  marker.active_next = op->active_next;
999 
1000  if (marker.active_next)
1001  marker.active_next->active_prev = &marker;
1002  marker.active_prev = op;
1003  op->active_next = &marker;
1004 
1005  /* Now process op */
1006  if (QUERY_FLAG(op, FLAG_FREED)) {
1007  LOG(llevError, "BUG: process_events(): Free object on list\n");
1008  op->speed = 0;
1009  object_update_speed(op);
1010  continue;
1011  }
1012 
1013  /* I've seen occasional crashes due to this - the object is removed,
1014  * and thus the map it points to (last map it was on) may be bogus
1015  * The real bug is to try to find out the cause of this - someone
1016  * is probably calling object_remove() without either an insert_ob or
1017  * object_free_drop_inventory() afterwards, leaving an object dangling.
1018  * But I'd rather log this and continue on instead of crashing.
1019  * Don't remove players - when a player quits, the object is in
1020  * sort of a limbo, of removed, but something we want to keep
1021  * around.
1022  */
1023  if (QUERY_FLAG(op, FLAG_REMOVED)
1024  && op->type != PLAYER
1025  && op->map
1026  && op->map->in_memory != MAP_IN_MEMORY) {
1027  StringBuffer *sb;
1028  char *diff;
1029 
1030  LOG(llevError, "BUG: process_events(): Removed object on list\n");
1031  sb = stringbuffer_new();
1032  object_dump(op, sb);
1033  diff = stringbuffer_finish(sb);
1034  LOG(llevError, "%s\n", diff);
1035  free(diff);
1037  continue;
1038  }
1039 
1040  if (!op->speed) {
1041  LOG(llevError, "BUG: process_events(): Object %s has no speed, but is on active list\n", op->arch->name);
1042  object_update_speed(op);
1043  continue;
1044  }
1045 
1046  if (op->map == NULL
1047  && op->env == NULL
1048  && op->name
1049  && op->type != MAP) {
1050  LOG(llevError, "BUG: process_events(): Object without map or inventory is on active list: %s (%d)\n", op->name, op->count);
1051  op->speed = 0;
1052  object_update_speed(op);
1053  continue;
1054  }
1055 
1056  /* Seen some cases where process_object() is crashing because
1057  * the object is on a swapped out map. But can't be sure if
1058  * something in the chain of events caused the object to
1059  * change maps or was just never removed - this will
1060  * give some clue as to its state before call to
1061  * process_object
1062  */
1063  if (op->map && op->map->in_memory != MAP_IN_MEMORY) {
1064  LOG(llevError, "BUG: process_events(): Processing object on swapped out map: %s (%d), map=%s\n", op->name, op->count, op->map->path);
1065  }
1066 
1067  /* Animate the object. Bug of feature that andim_speed
1068  * is based on ticks, and not the creatures speed?
1069  */
1070  if ((op->anim_speed && op->last_anim >= op->anim_speed)
1071  || (op->temp_animation_id && op->last_anim >= op->temp_anim_speed)) {
1072  op->state++;
1073  if ((op->type == PLAYER) || (op->type == MONSTER))
1074  animate_object(op, op->facing);
1075  else
1076  animate_object(op, op->direction);
1077  op->last_anim = 1;
1078  } else {
1079  op->last_anim++;
1080  }
1081 
1082  if (op->speed_left > 0) {
1083  --op->speed_left;
1084  process_object(op);
1085  if (object_was_destroyed(op, tag))
1086  continue;
1087  }
1088  if (settings.casting_time == TRUE && op->casting_time > 0)
1089  op->casting_time--;
1090  if (op->speed_left <= 0)
1091  op->speed_left += FABS(op->speed);
1092  }
1093 
1094  /* Remove marker object from active list */
1095  if (marker.active_prev != NULL)
1096  marker.active_prev->active_next = NULL;
1097  else
1098  active_objects = NULL;
1099 
1100  process_players2();
1101 }
1102 
1108 void clean_tmp_files(void) {
1109  mapstruct *m, *next;
1110 
1111  LOG(llevInfo, "Cleaning up...\n");
1112 
1113  /* We save the maps - it may not be intuitive why, but if there are unique
1114  * items, we need to save the map so they get saved off. Perhaps we should
1115  * just make a special function that only saves the unique items.
1116  */
1117  for (m = first_map; m != NULL; m = next) {
1118  next = m->next;
1119  if (m->in_memory == MAP_IN_MEMORY) {
1120  /* If we want to reuse the temp maps, swap it out (note that will also
1121  * update the log file. Otherwise, save the map (mostly for unique item
1122  * stuff). Note that the clean_tmp_map is called after the end of
1123  * the for loop but is in the #else bracket. IF we are recycling the maps,
1124  * we certainly don't want the temp maps removed.
1125  */
1126 
1127  /* XXX The above comment is dead wrong */
1129  swap_map(m);
1130  else {
1131  save_map(m, SAVE_MODE_NORMAL); /* note we save here into a overlay map */
1132  clean_tmp_map(m);
1133  }
1134  }
1135  }
1136  write_todclock(); /* lets just write the clock here */
1137 }
1138 
1140 void cleanup(void) {
1141  LOG(llevDebug, "Cleanup called. freeing data.\n");
1142  clean_tmp_files();
1144  accounts_save();
1145 
1146 #ifdef MEMORY_DEBUG
1147  free_all_maps();
1148  free_style_maps();
1149 #endif
1150  cleanupPlugins();
1151 #ifdef MEMORY_DEBUG
1152  free_all_archs();
1155  free_all_images();
1157  free_all_recipes();
1159  free_all_god();
1160  free_all_anim();
1161  i18n_free();
1162  free_loader();
1163  free_globals();
1164  free_server();
1166  free_knowledge();
1167  free_quest();
1169  /* See what the string data that is out there that hasn't been freed. */
1170  /* LOG(llevDebug, "%s", ss_dump_table(0xff));*/
1171 #endif
1172  exit(0);
1173 }
1174 
1183 void leave(player *pl, int draw_exit) {
1184  if (!QUERY_FLAG(pl->ob, FLAG_REMOVED)) {
1185  pets_terminate_all(pl->ob);
1186  object_remove(pl->ob);
1187  }
1188 
1189  pl->socket.status = Ns_Dead;
1190  LOG(llevInfo, "logout: %s from %s\n", pl->ob->name, pl->socket.host);
1191 
1192  strcpy(pl->ob->contr->killer, "left");
1193  hiscore_check(pl->ob, 1);
1194 
1195  /* If this player is the captain of the transport, need to do
1196  * some extra work. By the time we get here, object_remove()
1197  * should have already been called.
1198  */
1199  if (pl->transport && pl->transport->contr == pl) {
1200  /* If inv is a non player, inv->contr will be NULL, but that
1201  * is OK.
1202  */
1203  if (pl->transport->inv)
1204  pl->transport->contr = pl->transport->inv->contr;
1205  else
1206  pl->transport->contr = NULL;
1207 
1208  if (pl->transport->contr) {
1209  char name[MAX_BUF];
1210 
1211  query_name(pl->transport, name, MAX_BUF);
1214  "%s has left. You are now the captain of %s",
1215  pl->ob->name, name);
1216  }
1217  }
1218 
1219  if (pl->ob->map) {
1220  if (pl->ob->map->in_memory == MAP_IN_MEMORY)
1221  pl->ob->map->timeout = MAP_TIMEOUT(pl->ob->map);
1222  pl->ob->map = NULL;
1223  }
1224  pl->ob->type = DEAD_OBJECT; /* To avoid problems with inventory window */
1225  party_leave(pl->ob);
1226  /* If a hidden dm dropped connection do not create
1227  * inconsistencies by showing that they have left the game
1228  */
1229  if (!(QUERY_FLAG(pl->ob, FLAG_WIZ) && pl->ob->contr->hidden)
1230  && (pl != NULL && draw_exit) && (pl->state != ST_GET_NAME && pl->state != ST_GET_PASSWORD && pl->state != ST_CONFIRM_PASSWORD))
1233  "%s left the game.",
1234  pl->ob->name);
1235 }
1236 
1244 int forbid_play(void) {
1245 #if !defined(_IBMR2) && !defined(___IBMR2) && defined(PERM_FILE)
1246  char buf[MAX_BUF], day[MAX_BUF];
1247  FILE *fp;
1248  time_t clock;
1249  struct tm *tm;
1250  int i, start, stop, forbit = 0;
1251 
1252  clock = time(NULL);
1253  tm = (struct tm *)localtime(&clock);
1254 
1255  snprintf(buf, sizeof(buf), "%s/%s", settings.confdir, PERM_FILE);
1256  if ((fp = fopen(buf, "r")) == NULL)
1257  return 0;
1258 
1259  while (fgets(buf, sizeof(buf), fp)) {
1260  if (buf[0] == '#')
1261  continue;
1262  if (!strncmp(buf, "msg", 3)) {
1263  if (forbit)
1264  while (fgets(buf, sizeof(buf), fp)) /* print message */
1265  fputs(buf, logfile);
1266  break;
1267  } else if (sscanf(buf, "%s %d%*c%d\n", day, &start, &stop) != 3) {
1268  LOG(llevDebug, "Warning: Incomplete line in permission file ignored.\n");
1269  continue;
1270  }
1271 
1272  for (i = 0; i < 7; i++) {
1273  if (!strncmp(buf, days[i], 3)
1274  && (tm->tm_wday == i)
1275  && (tm->tm_hour >= start)
1276  && (tm->tm_hour < stop))
1277  forbit = 1;
1278  }
1279  }
1280 
1281  fclose(fp);
1282 
1283  return forbit;
1284 #else
1285  return 0;
1286 #endif
1287 }
1288 
1292 static void server_check_shutdown(void) {
1293  /* When to remind players of an imminent apocalypse. */
1294  const int warn_times[] = {120, 60, 30, 15, 10, 5, 3, 2, 1};
1295  static int next_warn = 0;
1296 
1297  time_t time_left;
1298  unsigned int i;
1299 
1300  /* Zero means that no shutdown is pending. */
1301  if (cmd_shutdown_time == 0) {
1302  return;
1303  }
1304 
1305  /* Remind players about the upcoming shutdown. */
1306  time_left = cmd_shutdown_time - time(NULL);
1307 
1308  for (i = next_warn; i < sizeof(warn_times) / sizeof(int); i++) {
1309  if (warn_times[i] == (int)ceil(time_left / 60.0)) {
1312  "Server shutting down in %d minutes.", warn_times[i]);
1313  next_warn = i + 1;
1314  break;
1315  }
1316  }
1317 
1318  /* Shutdown time has arrived; bring server down. */
1319  if (time_left <= 0) {
1321  MSG_TYPE_ADMIN_DM, "The server has shut down.");
1322 
1323  /* TODO: Kick everyone out and save player files? */
1324  cleanup();
1325  }
1326 }
1327 
1328 extern unsigned long todtick;
1329 
1344 static void do_specials(void) {
1345  if (!(pticks%10))
1347 
1348  if (pticks % 51 == 0) {
1350  }
1351 
1352 #ifdef WATCHDOG
1353  if (!(pticks%503))
1354  watchdog();
1355 #endif
1356 
1357  if (!(pticks%PTICKS_PER_CLOCK))
1358  tick_the_clock();
1359 
1360  if (!(pticks%509))
1361  flush_old_maps(); /* Clears the tmp-files of maps which have reset */
1362 
1363  if (!(pticks%2503))
1364  fix_weight(); /* Hack to fix weightproblems caused by bugs */
1365 
1366  if (!(pticks%2521))
1367  metaserver_update(); /* 2500 ticks is about 5 minutes */
1368 
1369  if (!(pticks%2531))
1370  accounts_save();
1371 
1372  if (!(pticks%5003))
1374 
1375  if (!(pticks%5009))
1377 
1378  if (!(pticks%5011))
1380 
1381  if (!(pticks%12503))
1382  fix_luck();
1383 }
1384 
1393 void server_main(int argc, char *argv[]) {
1394 #ifdef WIN32 /* ---win32 this sets the win32 from 0d0a to 0a handling */
1395  _fmode = _O_BINARY;
1396  bRunning = 1;
1397 #endif
1398 
1399 #ifndef WIN32
1400  /* Here we check that we aren't root or suid */
1401  if (getuid() == 0 || geteuid() == 0) {
1402  fprintf(stderr,
1403  "Running crossfire-server as root is a bad idea; aborting!\n"
1404  "Please run it again as a normal, unprivileged user.\n");
1405  exit(EXIT_FAILURE);
1406  }
1407 #endif
1408 
1409 #ifdef DEBUG_MALLOC_LEVEL
1410  malloc_debug(DEBUG_MALLOC_LEVEL);
1411 #endif
1412 
1413  init(argc, argv);
1414  initPlugins(); /* GROS - Init the Plugins */
1415 #ifdef WIN32
1416  while (bRunning) {
1417 #else
1418  while (TRUE) {
1419 #endif
1420  nroferrors = 0;
1421 
1422  do_server();
1423  process_events(); /* "do" something with objects with speed */
1424  cftimer_process_timers(); /* Process the crossfire Timers */
1425  /* Lauwenmark : Here we handle the CLOCK global event */
1427  check_active_maps(); /* Removes unused maps after a certain timeout */
1428  do_specials(); /* Routines called from time to time. */
1429 
1430  sleep_delta(); /* Sleep proper amount of time before next tick */
1431  }
1432 
1433  /* This is unreachable. */
1434  abort();
1435 }
void enter_exit(object *op, object *exit_ob)
Definition: server.c:709
EXTERN FILE * logfile
Definition: global.h:142
float weapon_speed_left
Definition: object.h:331
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Definition: main.c:315
#define AP_UNAPPLY
Definition: define.h:611
char path[HUGE_BUF]
Definition: map.h:365
int find_dir_2(int x, int y)
Definition: object.c:3600
void free_all_maps(void)
Definition: map.c:1977
char const * newhash(char const password[static 1])
Definition: server.c:90
void leave(player *pl, int draw_exit)
Definition: server.c:1183
#define MSG_TYPE_MISC
Definition: newclient.h:389
Definition: player.h:92
#define FLAG_DAMNED
Definition: define.h:318
mapstruct * mapfile_load(const char *map, int flags)
Definition: map.c:1237
mapstruct * generate_random_map(const char *OutFileName, RMParms *RP, char **use_layout)
Definition: random_map.c:74
void do_server(void)
Definition: loop.c:501
Definition: map.h:380
Definition: object.h:125
void enter_player_savebed(object *op)
Definition: server.c:121
void free_quest_definitions(void)
Definition: quest.c:1307
void cleanup(void)
Definition: server.c:1140
static void enter_random_map(object *pl, object *exit_ob)
Definition: server.c:361
static void do_specials(void)
Definition: server.c:1344
#define NDI_ALL
Definition: newclient.h:246
int16_t bed_x
Definition: player.h:98
#define FABS(x)
Definition: define.h:22
void object_free_all_data(void)
Definition: object.c:522
#define MSG_TYPE_COMMAND_FAILURE
Definition: newclient.h:511
void do_some_living(object *op)
Definition: player.c:3290
uint8_t anim_speed
Definition: object.h:417
void metaserver_update(void)
Definition: metaserver.c:49
uint8_t last_anim
Definition: object.h:418
int16_t players
Definition: map.h:344
char final_map[RM_SIZE]
Definition: random_map.h:52
char * create_pathname(const char *name, char *buf, size_t size)
Definition: map.c:104
int save_player(object *op, int flag)
Definition: login.c:211
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:57
uint32_t in_memory
Definition: map.h:345
mapstruct * ready_map_name(const char *name, int flags)
Definition: map.c:1817
const char * playerdir
Definition: global.h:244
int32_t last_heal
Definition: object.h:357
#define MAP_ENTER_X(m)
Definition: map.h:85
void free_string(sstring str)
Definition: shstr.c:280
#define HUGE_BUF
Definition: define.h:37
#define EVENT_MAPLEAVE
Definition: plugin.h:91
uint32_t is_template
Definition: map.h:338
uint32_t pticks
Definition: time.c:45
#define MAP_HEIGHT(m)
Definition: map.h:80
socket_struct socket
Definition: player.h:94
short freearr_x[SIZEOFFREE]
Definition: object.c:65
#define ST_CONFIRM_PASSWORD
Definition: define.h:584
region * get_region_by_map(mapstruct *m)
Definition: region.c:74
int32_t last_sp
Definition: object.h:358
object * ranges[range_size]
Definition: player.h:103
#define FREE_OBJ_NO_DESTROY_CALLBACK
Definition: object.h:533
#define AUTOSAVE
Definition: config.h:648
int8_t sounds_this_tick
Definition: newserver.h:133
void swap_below_max(const char *except_level)
Definition: swap.c:242
object * object_find_by_type_and_slaying(const object *who, int type, const char *slaying)
Definition: object.c:4052
enum Sock_Status status
Definition: newserver.h:100
#define object_was_destroyed(op, old_tag)
Definition: object.h:68
#define TRUE
Definition: compat.h:10
void party_leave(object *op)
Definition: party.c:104
#define PERM_FILE
Definition: config.h:500
#define SAVE_MODE_NORMAL
Definition: map.h:120
void remove_friendly_object(object *op)
Definition: friend.c:56
method_ret ob_apply(object *op, object *applier, int aflags)
Definition: ob_methods.c:42
void fix_weight(void)
Definition: player.c:3879
void enter_player_maplevel(object *op)
Definition: server.c:654
uint8_t temp_anim_speed
Definition: object.h:420
void i18n_free(void)
Definition: languages.c:252
void clean_friendly_list(void)
Definition: friend.c:111
#define safe_strncpy
Definition: compat.h:23
void free_quest(void)
Definition: quest.c:1289
uint32_t hidden
Definition: player.h:132
void pets_terminate_all(object *owner)
Definition: pets.c:231
static void enter_unique_map(object *op, object *exit_ob)
Definition: server.c:589
int swap_map(mapstruct *map)
Definition: swap.c:135
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: main.c:310
#define ST_PLAYING
Definition: define.h:577
char savebed_map[MAX_BUF]
Definition: player.h:97
#define NDI_DK_ORANGE
Definition: newclient.h:227
char * host
Definition: newserver.h:110
uint16_t temp_animation_id
Definition: object.h:419
uint8_t casting_time
Definition: global.h:266
uint8_t recycle_tmp_maps
Definition: global.h:268
uint16_t emergency_y
Definition: global.h:297
#define FLAG_REMOVED
Definition: define.h:232
void check_active_maps(void)
Definition: swap.c:195
short freearr_y[SIZEOFFREE]
Definition: object.c:71
int cmd_shutdown_time
Definition: c_wiz.c:43
object * active_objects
Definition: object.c:62
void free_all_newserver(void)
Definition: init.c:395
uint32_t ticks_played
Definition: player.h:203
#define MSG_TYPE_ADMIN_DM
Definition: newclient.h:475
void map_newmap_cmd(socket_struct *ns)
Definition: request.c:615
int forbid_play(void)
Definition: server.c:1244
char * name
Definition: map.h:328
#define MAP_IN_MEMORY
Definition: map.h:130
void object_free_drop_inventory(object *ob)
Definition: object.c:1368
int16_t y
Definition: object.h:326
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.c:1921
static void server_check_shutdown(void)
Definition: server.c:1292
void flush_old_maps(void)
Definition: swap.c:294
void free_loader(void)
#define MSG_TYPE_COMMAND
Definition: newclient.h:379
void object_dump(const object *op, StringBuffer *sb)
Definition: object.c:394
#define EVENT_MAPENTER
Definition: plugin.h:90
void write_todclock(void)
Definition: init.c:447
object * object_new(void)
Definition: object.c:1037
static char * clean_path(const char *file, char *newpath, int size)
Definition: server.c:307
void accounts_save(void)
Definition: account.c:267
float speed_left
Definition: object.h:329
static void enter_fixed_template_map(object *pl, object *exit_ob)
Definition: server.c:428
uint32_t unique
Definition: map.h:337
void free_all_treasures(void)
Definition: treasure.c:1597
#define MSG_TYPE_ADMIN_PLAYER
Definition: newclient.h:474
unsigned long todtick
Definition: init.c:441
struct mapdef * map
Definition: object.h:297
static void enter_random_template_map(object *pl, object *exit_ob)
Definition: server.c:521
#define snprintf
Definition: win32.h:46
struct obj * active_prev
Definition: object.h:283
int ob_blocked(const object *ob, mapstruct *m, int16_t x, int16_t y)
Definition: map.c:489
void free_all_anim(void)
Definition: anim.c:30
void server_main(int argc, char *argv[])
Definition: server.c:1393
object * transport
Definition: player.h:195
#define MAP_TIMEOUT(m)
Definition: map.h:66
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
Definition: path.c:172
int16_t dam
Definition: living.h:45
const char * name
Definition: object.h:311
int16_t bed_y
Definition: player.h:98
struct obj * env
Definition: object.h:293
struct quest_definition * next
Definition: quest.c:89
uint8_t state
Definition: object.h:349
int execute_global_event(int eventcode,...)
Definition: main.c:369
#define EXIT_PATH(xyz)
Definition: define.h:455
uint8_t state
Definition: player.h:118
#define INS_NO_WALK_ON
Definition: object.h:570
static void process_players1(void)
Definition: server.c:834
int16_t last_grace
Definition: object.h:359
#define MAP_MAXTIMEOUT
Definition: config.h:409
int8_t direction
Definition: object.h:334
void pets_remove_all(void)
Definition: pets.c:257
#define MAP_ENTER_Y(m)
Definition: map.h:87
static char * unclean_path(const char *src, char *newpath, int size)
Definition: server.c:335
void hiscore_check(object *op, int quiet)
Definition: hiscore.c:303
EXTERN long nroferrors
Definition: global.h:134
#define SIZEOFFREE
Definition: define.h:154
int bRunning
Definition: win32.c:159
uint16_t emergency_x
Definition: global.h:297
#define EXIT_X(xyz)
Definition: define.h:457
uint32_t has_hit
Definition: player.h:129
struct pl * contr
Definition: object.h:276
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:206
void free_globals(void)
Definition: init.c:327
void process_events(void)
Definition: server.c:970
uint32_t tag_t
Definition: object.h:12
void tick_the_clock(void)
Definition: weather.c:96
float speed
Definition: object.h:328
int process_object(object *op)
Definition: time.c:794
void init(int argc, char **argv)
Definition: init.c:995
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
void cleanupPlugins(void)
Definition: plugins.c:4778
void fix_luck(void)
Definition: player.c:3895
#define FLAG_WIZ
Definition: define.h:231
void clean_tmp_files(void)
Definition: server.c:1108
#define MAP_MINTIMEOUT
Definition: config.h:411
uint32_t golem_count
Definition: player.h:106
void knowledge_process_incremental(void)
Definition: knowledge.c:1447
#define EXIT_Y(xyz)
Definition: define.h:458
#define MAX_BUF
Definition: define.h:35
struct obj * active_next
Definition: object.h:279
#define MSG_TYPE_ADMIN
Definition: newclient.h:377
int16_t x
Definition: object.h:326
void free_all_images(void)
Definition: image.c:396
void free_all_archs(void)
Definition: arch.c:287
int32_t last_eat
Definition: object.h:356
int Ysize
Definition: random_map.h:70
int handle_newcs_player(object *op)
Definition: player.c:3096
void free_all_artifacts(void)
Definition: artifact.c:140
const char * confdir
Definition: global.h:241
static const flag_definition flags[]
int Xsize
Definition: random_map.h:69
void animate_object(object *op, int dir)
Definition: anim.c:212
int save_map(mapstruct *m, int flag)
Definition: map.c:1442
void free_all_recipes(void)
Definition: recipe.c:727
object * ob
Definition: player.h:158
int32_t timeout
Definition: map.h:341
char origin_map[RM_SIZE]
Definition: random_map.h:50
#define EVENT_CLOCK
Definition: plugin.h:84
Definition: object.h:107
static char const * crypt_string(char const str[static 1], char const *salt)
Definition: server.c:64
char killer[BIG_NAME]
Definition: player.h:171
void replace(const char *src, const char *key, const char *replacement, char *result, size_t resultsize)
Definition: utils.c:354
uint32_t attacktype
Definition: object.h:342
int set_random_map_variable(RMParms *rp, const char *buf)
#define RANDOM()
Definition: define.h:679
void sleep_delta(void)
Definition: time.c:180
#define PORTAL_DESTINATION_NAME
#define MAP_PLAYER_UNIQUE
Definition: map.h:97
const char * localdir
Definition: global.h:243
void party_obsolete_parties(void)
Definition: party.c:236
int origin_y
Definition: random_map.h:83
tag_t count
Definition: object.h:299
living stats
Definition: object.h:368
struct archt * arch
Definition: object.h:412
#define MAP_WIDTH(m)
Definition: map.h:78
unsigned int distance
Definition: map.h:381
uint8_t type
Definition: object.h:338
struct Settings settings
Definition: init.c:40
static void enter_map(object *op, mapstruct *newmap, int x, int y)
Definition: server.c:162
struct regiondef * region
Definition: random_map.h:91
void object_set_enemy(object *op, object *enemy)
Definition: object.c:679
void object_free2(object *ob, int flags)
Definition: object.c:1391
int out_of_map(mapstruct *m, int x, int y)
Definition: map.c:2308
void free_all_readable(void)
Definition: readable.c:2123
#define SIZEOFFREE2
Definition: define.h:153
void apply_auto_fix(mapstruct *m)
Definition: main.c:261
void cftimer_process_timers(void)
Definition: timers.c:44
const char * msg
Definition: object.h:322
int16_t casting_time
Definition: object.h:402
void write_book_archive(void)
Definition: readable.c:2172
uint8_t crypt_mode
Definition: global.h:327
sstring add_string(const char *str)
Definition: shstr.c:124
EXTERN player * first_player
Definition: global.h:117
struct pl * next
Definition: player.h:93
static const char * days[]
Definition: server.c:47
void initPlugins(void)
Definition: plugins.c:4728
void free_style_maps(void)
Definition: style.c:312
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
Definition: map.c:302
struct obj * inv
Definition: object.h:290
#define NDI_UNIQUE
Definition: newclient.h:245
#define SIZEOFFREE1
Definition: define.h:152
void watchdog(void)
char maplevel[MAX_BUF]
Definition: player.h:96
void player_update_bg_music(object *player)
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
void free_all_god(void)
Definition: holy.c:337
void free_knowledge(void)
Definition: knowledge.c:1288
struct mapdef * next
Definition: map.h:326
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
Definition: object.c:3415
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:626
char * emergency_mapname
Definition: global.h:296
Definition: map.h:325
void set_map_timeout(mapstruct *oldmap)
Definition: server.c:274
#define ST_GET_NAME
Definition: define.h:582
void free_server(void)
Definition: init.c:1035
#define FLAG_UNIQUE
Definition: define.h:288
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
Definition: attack.c:1869
int get_rangevector(object *op1, const object *op2, rv_vector *retval, int flags)
Definition: map.c:2541
int origin_x
Definition: random_map.h:84
void create_template_pathname(const char *name, char *buf, size_t size)
Definition: map.c:145
int8_t facing
Definition: object.h:335
float weapon_speed
Definition: object.h:330
void clean_tmp_map(mapstruct *m)
Definition: map.c:1968
player * find_player_partial_name(const char *plname)
Definition: player.c:109
EXTERN mapstruct * first_map
Definition: global.h:118
#define PTICKS_PER_CLOCK
Definition: tod.h:11
void object_update_speed(object *op)
Definition: object.c:1129
sstring followed_player
Definition: player.h:199
const char * name
Definition: object.h:466
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:76
#define P_NO_CLERIC
Definition: map.h:238
void object_remove(object *op)
Definition: object.c:1654
bool check_password(const char *typed, const char *crypted)
Definition: server.c:103
#define ST_GET_PASSWORD
Definition: define.h:583
static void process_players2(void)
Definition: server.c:944
#define FLAG_FREED
Definition: define.h:233
uint32_t count
Definition: player.h:109
Definition: object.h:224