Crossfire Server, Branches 1.12  R18729
server.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_server_c =
3  * "$Id: server.c 11578 2009-02-23 22:02:27Z lalo $";
4  */
5 
6 /*
7  CrossFire, A Multiplayer game for X-windows
8 
9  Copyright (C) 2006 Mark Wedel & Crossfire Development Team
10  Copyright (C) 1992 Frank Tore Johansen
11 
12  This program is free software; you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation; either version 2 of the License, or
15  (at your option) any later version.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 
26  The authors can be reached via e-mail at crossfire-devel@real-time.com
27 */
28 
34 #include <global.h>
35 #include <object.h>
36 #include <tod.h>
37 #include <version.h>
38 
39 #ifdef HAVE_DES_H
40 #include <des.h>
41 #else
42 # ifdef HAVE_CRYPT_H
43 # include <crypt.h>
44 # endif
45 #endif
46 
47 #ifndef __CEXTRACT__
48 #include <sproto.h>
49 #endif
50 
51 #ifdef HAVE_TIME_H
52 #include <time.h>
53 #endif
54 
55 #ifndef WIN32
56 # include <unistd.h>
57 # include <sys/types.h>
58 #endif
59 
60 #include <../random_maps/random_map.h>
61 #include <../random_maps/rproto.h>
62 #include "path.h"
63 
65 static const char days[7][4] = {
66  "Sun",
67  "Mon",
68  "Tue",
69  "Wed",
70  "Thu",
71  "Fri",
72  "Sat"
73 };
74 
81 void version(object *op) {
83  "This is Crossfire v%s",
84  "This is Crossfire v%s",
85  FULL_VERSION);
87  "The authors can be reached at crossfire@metalforge.org", NULL);
88 
89 }
90 
97 void start_info(object *op) {
99  "Welcome to Crossfire, v%s!\nPress `?' for help\n",
100  "Welcome to Crossfire, v%s!\nPress `?' for help\n",
101  VERSION);
102 
105  "%s entered the game.",
106  "%s entered the game.",
107  op->name);
108 
109  if (!op->contr->name_changed) {
111  "Note that you must set your name with the name command to enter the highscore list.", NULL);
112  }
113 }
114 
130 char *crypt_string(char *str, char *salt) {
131 #if defined(WIN32) || (defined(__FreeBSD__) && !defined(HAVE_LIBDES))
132  return(str);
133 #else
134  static const char *const c = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
135  char s[2];
136 
137  if (salt == NULL)
138  s[0] = c[RANDOM()%(int)strlen(c)],
139  s[1] = c[RANDOM()%(int)strlen(c)];
140  else
141  s[0] = salt[0],
142  s[1] = salt[1];
143 
144 # ifdef HAVE_LIBDES
145  return (char *)des_crypt(str, s);
146 # endif
147  /* Default case - just use crypt */
148  return (char *)crypt(str, s);
149 #endif
150 }
151 
162 int check_password(char *typed, char *crypted) {
163  return !strcmp(crypt_string(typed, crypted), crypted);
164 }
165 
175 void enter_player_savebed(object *op) {
176  mapstruct *oldmap = op->map;
177  object *tmp;
178 
179  tmp = get_object();
180 
181  EXIT_PATH(tmp) = add_string(op->contr->savebed_map);
182  EXIT_X(tmp) = op->contr->bed_x;
183  EXIT_Y(tmp) = op->contr->bed_y;
184  enter_exit(op, tmp);
185  /* If the player has not changed maps and the name does not match
186  * that of the savebed, his savebed map is gone. Lets go back
187  * to the emergency path. Update what the players savebed is
188  * while we're at it.
189  */
190  if (oldmap == op->map && strcmp(op->contr->savebed_map, oldmap->path)) {
191  LOG(llevDebug, "Player %s savebed location %s is invalid - going to emergency location (%s)\n", settings.emergency_mapname, op->name, op->contr->savebed_map);
196  EXIT_PATH(tmp) = add_string(op->contr->savebed_map);
197  EXIT_X(tmp) = op->contr->bed_x;
198  EXIT_Y(tmp) = op->contr->bed_y;
199  enter_exit(op, tmp);
200  }
201  free_object(tmp);
202 }
203 
215 static void enter_map(object *op, mapstruct *newmap, int x, int y) {
216  mapstruct *oldmap = op->map;
217 
218  if (out_of_map(newmap, x, y)) {
219  LOG(llevError, "enter_map: supplied coordinates are not within the map! (%s: %d, %d)\n", newmap->path, x, y);
220  x = MAP_ENTER_X(newmap);
221  y = MAP_ENTER_Y(newmap);
222  if (out_of_map(newmap, x, y)) {
223  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));
225  "The exit is closed", NULL);
226  return;
227  }
228  }
229  /* try to find a spot for the player */
230  if (ob_blocked(op, newmap, x, y)) { /* First choice blocked */
231  /* We try to find a spot for the player, starting closest in.
232  * We could use find_first_free_spot, but that doesn't randomize it at all,
233  * So for example, if the north space is free, you would always end up there even
234  * if other spaces around are available.
235  * Note that for the second and third calls, we could start at a position other
236  * than one, but then we could end up on the other side of walls and so forth.
237  */
238  int i = find_free_spot(op, newmap, x, y, 1, SIZEOFFREE1+1);
239  if (i == -1) {
240  i = find_free_spot(op, newmap, x, y, 1, SIZEOFFREE2+1);
241  if (i == -1)
242  i = find_free_spot(op, newmap, x, y, 1, SIZEOFFREE);
243  }
244  if (i != -1) {
245  x += freearr_x[i];
246  y += freearr_y[i];
247  } else {
248  /* not much we can do in this case. */
249  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);
250  }
251  } /* end if looking for free spot */
252 
253  /* If it is a player login, he has yet to be inserted anyplace.
254  * otherwise, we need to deal with removing the playe here.
255  */
256  if (!QUERY_FLAG(op, FLAG_REMOVED))
257  remove_ob(op);
258  if (op->map != NULL) {
259  /* Lauwenmark : Here we handle the MAPLEAVE global event */
261  }
262  /* remove_ob clears these so they must be reset after the remove_ob call */
263  op->x = x;
264  op->y = y;
265  op->map = newmap;
266  insert_ob_in_map(op, op->map, NULL, INS_NO_WALK_ON);
267 
268  /* Lauwenmark : Here we handle the MAPENTER global event */
270 
271  if (op->contr) {
273  }
274 
275  newmap->timeout = 0;
276  op->enemy = NULL;
277 
278  if (op->contr) {
279  strcpy(op->contr->maplevel, newmap->path);
280  op->contr->count = 0;
281  }
282 
283  /* Update any golems */
284  if (op->type == PLAYER && op->contr->ranges[range_golem] != NULL) {
285  int i = find_free_spot(op->contr->ranges[range_golem], newmap, x, y, 1, SIZEOFFREE);
287  if (i == -1) {
290  op->contr->ranges[range_golem] = NULL;
291  op->contr->golem_count = 0;
292  } else {
293  object *tmp;
294 
295  for (tmp = op->contr->ranges[range_golem]; tmp != NULL; tmp = tmp->more) {
296  tmp->x = x+freearr_x[i]+(tmp->arch == NULL ? 0 : tmp->arch->clone.x);
297  tmp->y = y+freearr_y[i]+(tmp->arch == NULL ? 0 : tmp->arch->clone.y);
298  tmp->map = newmap;
299  }
300  insert_ob_in_map(op->contr->ranges[range_golem], newmap, NULL, 0);
302  }
303  }
304  op->direction = 0;
305 
306  /* since the players map is already loaded, we don't need to worry
307  * about pending objects.
308  */
309  remove_all_pets();
310 
311  /* If the player is changing maps, we need to do some special things
312  * Do this after the player is on the new map - otherwise the force swap of the
313  * old map does not work.
314  */
315  if (oldmap != newmap) {
316  if (oldmap) { /* adjust old map */
317  if (oldmap->players <= 0) /* can be less than zero due to errors in tracking this */
318  set_map_timeout(oldmap);
319  }
320  }
321  swap_below_max(newmap->path);
322 
323  if (op->type == PLAYER)
324  map_newmap_cmd(&op->contr->socket);
325 }
326 
333 void set_map_timeout(mapstruct *oldmap) {
334 #if MAP_MAXTIMEOUT
335  oldmap->timeout = MAP_TIMEOUT(oldmap);
336  /* Do MINTIMEOUT first, so that MAXTIMEOUT is used if that is
337  * lower than the min value.
338  */
339 #if MAP_MINTIMEOUT
340  if (oldmap->timeout < MAP_MINTIMEOUT) {
341  oldmap->timeout = MAP_MINTIMEOUT;
342  }
343 #endif
344  if (oldmap->timeout > MAP_MAXTIMEOUT) {
345  oldmap->timeout = MAP_MAXTIMEOUT;
346  }
347 #else
348  /* save out the map */
349  swap_map(oldmap);
350 #endif /* MAP_MAXTIMEOUT */
351 }
352 
366 static char *clean_path(const char *file, char *newpath, int size) {
367  char *cp;
368 
369  snprintf(newpath, size, "%s", file);
370  for (cp = newpath; *cp != '\0'; cp++) {
371  if (*cp == '/')
372  *cp = '_';
373  }
374  return newpath;
375 }
376 
394 static char *unclean_path(const char *src, char *newpath, int size) {
395  char *cp;
396 
397  cp = strrchr(src, '/');
398  if (cp)
399  snprintf(newpath, size, "%s", cp+1);
400  else
401  snprintf(newpath, size, "%s", src);
402 
403  for (cp = newpath; *cp != '\0'; cp++) {
404  if (*cp == '_')
405  *cp = '/';
406  }
407  return newpath;
408 }
409 
410 
420 static void enter_random_map(object *pl, object *exit_ob) {
421  mapstruct *new_map;
422  char newmap_name[HUGE_BUF], *cp;
423  static int reference_number = 0;
424  RMParms rp;
425 
426  memset(&rp, 0, sizeof(RMParms));
427  rp.Xsize = -1;
428  rp.Ysize = -1;
429  rp.region = get_region_by_map(exit_ob->map);
430  if (exit_ob->msg)
431  set_random_map_variable(&rp, exit_ob->msg);
432  rp.origin_x = exit_ob->x;
433  rp.origin_y = exit_ob->y;
434  strcpy(rp.origin_map, pl->map->path);
435 
436  /* If we have a final_map, use it as a base name to give some clue
437  * as where the player is. Otherwise, use the origin map.
438  * Take the last component (after the last slash) to give
439  * shorter names without bogus slashes.
440  */
441  if (rp.final_map[0]) {
442  cp = strrchr(rp.final_map, '/');
443  if (!cp)
444  cp = rp.final_map;
445  } else {
446  char buf[HUGE_BUF];
447 
448  cp = strrchr(rp.origin_map, '/');
449  if (!cp)
450  cp = rp.origin_map;
451  /* Need to strip of any trailing digits, if it has them */
452  snprintf(buf, sizeof(buf), "%s", cp);
453  while (isdigit(buf[strlen(buf)-1]))
454  buf[strlen(buf)-1] = 0;
455  cp = buf;
456  }
457 
458  snprintf(newmap_name, sizeof(newmap_name), "/random/%s%04d", cp+1, reference_number++);
459 
460  /* now to generate the actual map. */
461  new_map = generate_random_map(newmap_name, &rp, NULL);
462 
463  /* Update the exit_ob so it now points directly at the newly created
464  * random maps. Not that it is likely to happen, but it does mean that a
465  * exit in a unique map leading to a random map will not work properly.
466  * It also means that if the created random map gets reset before
467  * the exit leading to it, that the exit will no longer work.
468  */
469  if (new_map) {
470  int x, y;
471 
472  x = EXIT_X(exit_ob) = MAP_ENTER_X(new_map);
473  y = EXIT_Y(exit_ob) = MAP_ENTER_Y(new_map);
474  EXIT_PATH(exit_ob) = add_string(newmap_name);
475  snprintf(new_map->path, sizeof(new_map->path), "%s", newmap_name);
476  enter_map(pl, new_map, x, y);
477  }
478 }
479 
489 static void enter_fixed_template_map(object *pl, object *exit_ob) {
490  mapstruct *new_map;
491  char tmpnum[32], exitpath[HUGE_BUF], resultname[HUGE_BUF], tmpstring[HUGE_BUF], *sourcemap;
492  char new_map_name[MAX_BUF];
493 
494  /* Split the exit path string into two parts, one
495  * for where to store the map, and one for were
496  * to generate the map from.
497  */
498  snprintf(exitpath, sizeof(exitpath), "%s", EXIT_PATH(exit_ob)+2);
499  sourcemap = strchr(exitpath, '!');
500  if (!sourcemap) {
503  "The %s is closed.",
504  "The %s is closed.",
505  exit_ob->name);
506  /* Should only occur when no source map is set.
507  */
508  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);
509  return;
510  }
511  *sourcemap++ = '\0';
512 
513  /* If we are not coming from a template map, we can use relative directories
514  * for the map to generate from.
515  */
516  if (!exit_ob->map->is_template) {
517  /* We can't use exitpath directly, as sourcemap points there. */
518  path_combine_and_normalize(exit_ob->map->path, sourcemap, tmpstring, sizeof(tmpstring));
519  snprintf(exitpath, sizeof(exitpath), "%s", tmpstring);
520  sourcemap = exitpath;
521  }
522 
523  /* Do replacement of %x, %y, and %n to the x coord of the exit, the y coord
524  * of the exit, and the name of the map the exit is on, respectively.
525  */
526  snprintf(tmpnum, sizeof(tmpnum), "%d", exit_ob->x);
527  replace(exitpath, "%x", tmpnum, resultname, sizeof(resultname));
528 
529  snprintf(tmpnum, sizeof(tmpnum), "%d", exit_ob->y);
530  snprintf(tmpstring, sizeof(tmpstring), "%s", resultname);
531  replace(tmpstring, "%y", tmpnum, resultname, sizeof(resultname));
532 
533  snprintf(tmpstring, sizeof(tmpstring), "%s", resultname);
534  replace(tmpstring, "%n", exit_ob->map->name, resultname, sizeof(resultname));
535 
536  /* If we are coming from another template map, use reletive paths unless
537  * indicated otherwise.
538  */
539  if (exit_ob->map->is_template && (resultname[0] != '/')) {
540  path_combine_and_normalize(exit_ob->map->path, resultname, new_map_name, sizeof(new_map_name));
541  } else {
542  create_template_pathname(resultname, new_map_name, sizeof(new_map_name));
543  }
544 
545  /* Attempt to load the map, if unable to, then
546  * create the map from the template.
547  */
548  new_map = ready_map_name(new_map_name, MAP_PLAYER_UNIQUE);
549  if (!new_map) {
550  char path[MAX_BUF];
551 
552  create_pathname(sourcemap, path, MAX_BUF);
553  new_map = load_original_map(path, MAP_PLAYER_UNIQUE);
554  if (new_map)
555  fix_auto_apply(new_map);
556  }
557 
558  if (new_map) {
559  /* set the path of the map to where it should be
560  * so we don't just save over the source map.
561  */
562  snprintf(new_map->path, sizeof(new_map->path), "%s", new_map_name);
563  new_map->is_template = 1;
564  enter_map(pl, new_map, EXIT_X(exit_ob), EXIT_Y(exit_ob));
565  } else {
568  "The %s is closed.",
569  "The %s is closed.",
570  exit_ob->name);
571  /* Should only occur when an invalid source map is set.
572  */
573  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);
574  }
575 }
576 
586 static void enter_random_template_map(object *pl, object *exit_ob) {
587  mapstruct *new_map;
588  char tmpnum[32], resultname[HUGE_BUF], tmpstring[HUGE_BUF];
589  char new_map_name[MAX_BUF];
590  RMParms rp;
591 
592  /* Do replacement of %x, %y, and %n to the x coord of the exit, the y coord
593  * of the exit, and the name of the map the exit is on, respectively.
594  */
595  snprintf(tmpnum, sizeof(tmpnum), "%d", exit_ob->x);
596  replace(EXIT_PATH(exit_ob)+3, "%x", tmpnum, resultname, sizeof(resultname));
597 
598  snprintf(tmpnum, sizeof(tmpnum), "%d", exit_ob->y);
599  snprintf(tmpstring, sizeof(tmpstring), "%s", resultname);
600  replace(tmpstring, "%y", tmpnum, resultname, sizeof(resultname));
601 
602  snprintf(tmpstring, sizeof(tmpstring), "%s", resultname);
603  replace(tmpstring, "%n", exit_ob->map->name, resultname, sizeof(resultname));
604 
605  /* If we are coming from another template map, use reletive paths unless
606  * indicated otherwise.
607  */
608  if (exit_ob->map->is_template && (resultname[0] != '/')) {
609  path_combine_and_normalize(exit_ob->map->path, resultname, new_map_name, sizeof(new_map_name));
610  } else {
611  create_template_pathname(resultname, new_map_name, sizeof(new_map_name));
612  }
613 
614  new_map = ready_map_name(new_map_name, MAP_PLAYER_UNIQUE);
615  if (!new_map) {
616  memset(&rp, 0, sizeof(RMParms));
617  rp.Xsize = -1;
618  rp.Ysize = -1;
619  rp.region = get_region_by_map(exit_ob->map);
620  if (exit_ob->msg)
621  set_random_map_variable(&rp, exit_ob->msg);
622  rp.origin_x = exit_ob->x;
623  rp.origin_y = exit_ob->y;
624  strcpy(rp.origin_map, pl->map->path);
625 
626  /* now to generate the actual map. */
627  new_map = generate_random_map(new_map_name, &rp, NULL);
628  }
629 
630  /* Update the exit_ob so it now points directly at the newly created
631  * random maps. Not that it is likely to happen, but it does mean that a
632  * exit in a unique map leading to a random map will not work properly.
633  * It also means that if the created random map gets reset before
634  * the exit leading to it, that the exit will no longer work.
635  */
636  if (new_map) {
637  int x, y;
638 
639  x = EXIT_X(exit_ob) = MAP_ENTER_X(new_map);
640  y = EXIT_Y(exit_ob) = MAP_ENTER_Y(new_map);
641  new_map->is_template = 1;
642  enter_map(pl, new_map, x, y);
643  }
644 }
645 
654 static void enter_unique_map(object *op, object *exit_ob) {
655  char apartment[HUGE_BUF], path[MAX_BUF];
656  mapstruct *newmap;
657 
658  if (EXIT_PATH(exit_ob)[0] == '/') {
659  snprintf(apartment, sizeof(apartment), "%s/%s/%s/%s", settings.localdir, settings.playerdir, op->name, clean_path(EXIT_PATH(exit_ob), path, sizeof(path)));
660  newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE);
661  if (!newmap) {
662  create_pathname(EXIT_PATH(exit_ob), path, sizeof(path));
663  newmap = load_original_map(path, MAP_PLAYER_UNIQUE);
664  if (newmap)
665  fix_auto_apply(newmap);
666  }
667  } else { /* relative directory */
668  char reldir[HUGE_BUF], tmpc[HUGE_BUF], *cp;
669 
670  if (exit_ob->map->unique) {
671 
672  unclean_path(exit_ob->map->path, reldir, sizeof(reldir));
673 
674  /* Need to copy this over, as clean_path only has one static return buffer */
675  clean_path(reldir, tmpc, sizeof(tmpc));
676  /* Remove final component, if any */
677  if ((cp = strrchr(tmpc, '_')) != NULL)
678  *cp = 0;
679 
680  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)));
681 
682  newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE);
683  if (!newmap) {
684  create_pathname(path_combine_and_normalize(reldir, EXIT_PATH(exit_ob), tmpc, sizeof(tmpc)), path, sizeof(path));
685  newmap = load_original_map(path, MAP_PLAYER_UNIQUE);
686  if (newmap)
687  fix_auto_apply(newmap);
688  }
689  } else {
690  /* The exit is unique, but the map we are coming from is not unique. So
691  * use the basic logic - don't need to demangle the path name
692  */
693  path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob), reldir, sizeof(reldir));
694  snprintf(apartment, sizeof(apartment), "%s/%s/%s/%s", settings.localdir, settings.playerdir, op->name, clean_path(reldir, path, sizeof(path)));
695  newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE);
696  if (!newmap) {
697  path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob), reldir, sizeof(reldir));
698  newmap = ready_map_name(reldir, 0);
699  if (newmap)
700  fix_auto_apply(newmap);
701  }
702  }
703  }
704 
705  if (newmap) {
706  snprintf(newmap->path, sizeof(newmap->path), "%s", apartment);
707  newmap->unique = 1;
708  enter_map(op, newmap, EXIT_X(exit_ob), EXIT_Y(exit_ob));
709  } else {
712  "The %s is closed.",
713  "The %s is closed.",
714  exit_ob->name);
715  /* Perhaps not critical, but I would think that the unique maps
716  * should be new enough this does not happen. This also creates
717  * a strange situation where some players could perhaps have visited
718  * such a map before it was removed, so they have the private
719  * map, but other players can't get it anymore.
720  */
721  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);
722  }
723 
724 }
725 
740 void enter_exit(object *op, object *exit_ob) {
741 #define PORTAL_DESTINATION_NAME "Town portal destination" /* this one should really be in a header file */
742  object *tmp;
743  /* It may be nice to support other creatures moving across
744  * exits, but right now a lot of the code looks at op->contr,
745  * so thta is an RFE.
746  */
747  if (op->type != PLAYER)
748  return;
749 
750  /* Need to remove player from transport */
751  if (op->contr->transport)
752  ob_apply(op->contr->transport, op, AP_UNAPPLY);
753 
754  /* First, lets figure out what map the player is going to go to */
755  if (exit_ob) {
756  /* check to see if we make a template map */
757  if (EXIT_PATH(exit_ob) && EXIT_PATH(exit_ob)[1] == '@') {
758  if (EXIT_PATH(exit_ob)[2] == '!') {
759  /* generate a template map randomly */
760  enter_random_template_map(op, exit_ob);
761  } else {
762  /* generate a template map from a fixed template */
763  enter_fixed_template_map(op, exit_ob);
764  }
765  }
766  /* check to see if we make a randomly generated map */
767  else if (EXIT_PATH(exit_ob) && EXIT_PATH(exit_ob)[1] == '!') {
768  enter_random_map(op, exit_ob);
769  } else if (QUERY_FLAG(exit_ob, FLAG_UNIQUE)) {
770  enter_unique_map(op, exit_ob);
771  } else {
772  int x = EXIT_X(exit_ob), y = EXIT_Y(exit_ob);
773  /* 'Normal' exits that do not do anything special
774  * Simple enough we don't need another routine for it.
775  */
776  mapstruct *newmap;
777  if (exit_ob->map) {
778  char tmp_path[HUGE_BUF];
779 
780  path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob), tmp_path, sizeof(tmp_path));
781  newmap = ready_map_name(tmp_path, 0);
782  /* Random map was previously generated, but is no longer about. Lets generate a new
783  * map.
784  */
785  if (!newmap && !strncmp(EXIT_PATH(exit_ob), "/random/", 8)) {
786  /* Maps that go down have a message set. However, maps that go
787  * up, don't. If the going home has reset, there isn't much
788  * point generating a random map, because it won't match the maps.
789  */
790  if (exit_ob->msg) {
791  enter_random_map(op, exit_ob);
792  } else {
795  "The %s is closed.",
796  "The %s is closed.",
797  exit_ob->name);
798  return;
799  }
800 
801  /* For exits that cause damages (like pits). Don't know if any
802  * random maps use this or not.
803  */
804  if (exit_ob->stats.dam && op->type == PLAYER)
805  hit_player(op, exit_ob->stats.dam, exit_ob, exit_ob->attacktype, 1);
806  return;
807  }
808  } else {
809  /* For word of recall and other force objects
810  * They contain the full pathname of the map to go back to,
811  * so we don't need to normalize it.
812  * But we do need to see if it is unique or not
813  */
814  if (!strncmp(EXIT_PATH(exit_ob), settings.localdir, strlen(settings.localdir)))
815  newmap = ready_map_name(EXIT_PATH(exit_ob), MAP_PLAYER_UNIQUE);
816  else
817  newmap = ready_map_name(EXIT_PATH(exit_ob), 0);
818  }
819  if (!newmap) {
820  if (exit_ob->name)
823  "The %s is closed.",
824  "The %s is closed.",
825  exit_ob->name);
826  /* don't cry to momma if name is not set - as in tmp objects
827  * used by the savebed code and character creation */
828  return;
829  }
830 
831  /* This supports the old behaviour, but it really should not be used.
832  * I will note for example that with this method, it is impossible to
833  * set 0,0 destination coordinates. Really, if we want to support
834  * using the new maps default coordinates, the exit ob should use
835  * something like -1, -1 so it is clear to do that.
836  */
837  if (x == 0 && y == 0) {
838  x = MAP_ENTER_X(newmap);
839  y = MAP_ENTER_Y(newmap);
840  LOG(llevDebug, "enter_exit: Exit %s (%d,%d) on map %s is 0 destination coordinates\n",
841  exit_ob->name ? exit_ob->name : "(none)", exit_ob->x, exit_ob->y,
842  exit_ob->map ? exit_ob->map->path : "(none)");
843  }
844 
845  /* mids 02/13/2002 if exit is damned, update players death & WoR home-position and delete town portal */
846  if (QUERY_FLAG(exit_ob, FLAG_DAMNED)) {
847  /* remove an old force with a slaying field == PORTAL_DESTINATION_NAME */
848  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
849  if (tmp->type == FORCE && tmp->slaying && !strcmp(tmp->slaying, PORTAL_DESTINATION_NAME))
850  break;
851  }
852  if (tmp) {
853  remove_ob(tmp);
854  free_object(tmp);
855  }
856 
857  path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob), op->contr->savebed_map, sizeof(op->contr->savebed_map));
858  op->contr->bed_x = EXIT_X(exit_ob), op->contr->bed_y = EXIT_Y(exit_ob);
859  save_player(op, 1);
860  /* LOG(llevDebug, "enter_exit: Taking damned exit %s to (%d,%d) on map %s\n",
861  * exit_ob->name ? exit_ob->name : "(none)", exit_ob->x, exit_ob->y,
862  * path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob))); */
863  }
864 
865  enter_map(op, newmap, x, y);
866  }
867  /* For exits that cause damages (like pits) */
868  if (exit_ob->stats.dam && op->type == PLAYER)
869  hit_player(op, exit_ob->stats.dam, exit_ob, exit_ob->attacktype, 1);
870  } else {
871  int flags = 0;
872  mapstruct *newmap;
873 
874  /* Hypothetically, I guess its possible that a standard map matches
875  * the localdir, but that seems pretty unlikely - unlikely enough that
876  * I'm not going to attempt to try to deal with that possibility.
877  * We use the fact that when a player saves on a unique map, it prepends
878  * the localdir to that name. So its an easy way to see of the map is
879  * unique or not.
880  */
881  if (!strncmp(op->contr->maplevel, settings.localdir, strlen(settings.localdir)))
882  flags = MAP_PLAYER_UNIQUE;
883 
884  /* newmap returns the map (if already loaded), or loads it for us. */
885  newmap = ready_map_name(op->contr->maplevel, flags);
886  if (!newmap) {
887  LOG(llevError, "enter_exit: Pathname to map does not exist! (%s)\n", op->contr->maplevel);
889  op->x = settings.emergency_x;
890  op->y = settings.emergency_y;
891  /* If we can't load the emergency map, something is probably really
892  * screwed up, so bail out now.
893  */
894  if (!newmap) {
895  LOG(llevError, "enter_exit: could not load emergency map? Fatal error\n");
896  abort();
897  }
898  }
899  enter_map(op, newmap, op->x, op->y);
900  }
901 }
902 
908 static void process_players1(void) {
909  int flag;
910  player *pl, *plnext;
911 
912  /* Basically, we keep looping until all the players have done their actions. */
913  for (flag = 1; flag != 0; ) {
914  flag = 0;
915  for (pl = first_player; pl != NULL; pl = plnext) {
916  plnext = pl->next; /* In case a player exits the game in handle_player() */
917 
918  if (pl->ob == NULL)
919  continue;
920 
922  if (pl->followed_player) {
924  if (followed && followed->ob && followed->ob->map) {
925  rv_vector rv;
926 
927  get_rangevector(pl->ob, followed->ob, &rv, 0);
928  if (rv.distance > 4) {
929  int space = find_free_spot(pl->ob, followed->ob->map, followed->ob->x, followed->ob->y, 1, 25);
930  if (space == -1)
932  space = 0;
933  remove_ob(pl->ob);
934  insert_ob_in_map_at(pl->ob, followed->ob->map, NULL, 0, followed->ob->x+freearr_x[space], followed->ob->y+freearr_y[space]);
935  map_newmap_cmd(&pl->socket);
936  }
937  } else {
938  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Player %s left or ambiguous name.", NULL, pl->followed_player);
940  }
941  }
943  if (pl->ob->speed_left > 0) {
944  if (handle_newcs_player(pl->ob))
945  flag = 1;
946  } /* end if player has speed left */
947 
948  /* If the player is not actively playing, don't make a
949  * backup save - nothing to save anyway. Plus, the
950  * map may not longer be valid. This can happen when the
951  * player quits - they exist for purposes of tracking on the map,
952  * but don't actually reside on any actual map.
953  */
954  if (QUERY_FLAG(pl->ob, FLAG_REMOVED))
955  continue;
956 
957 #ifdef AUTOSAVE
958  /* check for ST_PLAYING state so that we don't try to save off when
959  * the player is logging in.
960  */
961  if ((pl->last_save_tick+AUTOSAVE) < pticks && pl->state == ST_PLAYING) {
962  /* Don't save the player on unholy ground. Instead, increase the
963  * tick time so it will be about 10 seconds before we try and save
964  * again.
965  */
966  if (get_map_flags(pl->ob->map, NULL, pl->ob->x, pl->ob->y, NULL, NULL)&P_NO_CLERIC) {
967  pl->last_save_tick += 100;
968  } else {
969  save_player(pl->ob, 1);
970  pl->last_save_tick = pticks;
971  check_score(pl->ob, 1);
972  }
973  }
974 #endif
975  } /* end of for loop for all the players */
976  } /* for flag */
977  for(pl=first_player;pl!=NULL;pl=pl->next) {
978  pl->socket.sounds_this_tick = 0;
979  if (settings.casting_time == TRUE) {
980  if (pl->ob->casting_time > 0){
981  pl->ob->casting_time--;
982  }
983  }
984  do_some_living(pl->ob);
985 /* draw(pl->ob);*/ /* updated in socket code */
986  }
987 }
988 
996 static void process_players2(void) {
997  player *pl;
998 
999  /* Then check if any players should use weapon-speed instead of speed */
1000  for (pl=first_player;pl!=NULL;pl=pl->next) {
1001 
1002  /* The code that did weapon_sp handling here was out of place -
1003  * this isn't called until after the player has finished there
1004  * actions, and is thus out of place. All we do here is bounds
1005  * checking.
1006  */
1007  if (pl->has_hit) {
1008  if (pl->ob->speed_left > pl->weapon_sp) pl->ob->speed_left = pl->weapon_sp;
1009 
1010  /* This needs to be here - if the player is running, we need to
1011  * clear this each tick, but new commands are not being received
1012  * so execute_newserver_command() is never called
1013  */
1014  pl->has_hit=0;
1015 
1016  } else if (pl->ob->speed_left > pl->ob->speed)
1017  pl->ob->speed_left = pl->ob->speed;
1018  }
1019 }
1020 
1021 #define SPEED_DEBUG
1022 
1026 void process_events(void) {
1027  object *op;
1028  object marker;
1029  tag_t tag;
1030 
1031  process_players1();
1032 
1033  memset(&marker, 0, sizeof(object));
1034  /* Put marker object at beginning of active list */
1035  marker.active_next = active_objects;
1036 
1037  if (marker.active_next)
1038  marker.active_next->active_prev = &marker;
1039  marker.active_prev = NULL;
1040  active_objects = &marker;
1041 
1042  while (marker.active_next) {
1043  op = marker.active_next;
1044  tag = op->count;
1045 
1046  /* Move marker forward - swap op and marker */
1047  op->active_prev = marker.active_prev;
1048 
1049  if (op->active_prev)
1050  op->active_prev->active_next = op;
1051  else
1052  active_objects = op;
1053 
1054  marker.active_next = op->active_next;
1055 
1056  if (marker.active_next)
1057  marker.active_next->active_prev = &marker;
1058  marker.active_prev = op;
1059  op->active_next = &marker;
1060 
1061  /* Now process op */
1062  if (QUERY_FLAG(op, FLAG_FREED)) {
1063  LOG(llevError, "BUG: process_events(): Free object on list\n");
1064  op->speed = 0;
1065  update_ob_speed(op);
1066  continue;
1067  }
1068 
1069  /* I've seen occasional crashes due to this - the object is removed,
1070  * and thus the map it points to (last map it was on) may be bogus
1071  * The real bug is to try to find out the cause of this - someone
1072  * is probably calling remove_ob without either an insert_ob or
1073  * free_object afterwards, leaving an object dangling. But I'd
1074  * rather log this and continue on instead of crashing.
1075  * Don't remove players - when a player quits, the object is in
1076  * sort of a limbo, of removed, but something we want to keep
1077  * around.
1078  */
1079  if (QUERY_FLAG(op, FLAG_REMOVED)
1080  && op->type != PLAYER
1081  && op->map
1082  && op->map->in_memory != MAP_IN_MEMORY) {
1083  StringBuffer *sb;
1084  char *diff;
1085 
1086  LOG(llevError, "BUG: process_events(): Removed object on list\n");
1087  sb = stringbuffer_new();
1088  dump_object(op, sb);
1089  diff = stringbuffer_finish(sb);
1090  LOG(llevError, "%s\n", diff);
1091  free(diff);
1092  free_object(op);
1093  continue;
1094  }
1095 
1096  if (!op->speed) {
1097  LOG(llevError, "BUG: process_events(): Object %s has no speed, but is on active list\n", op->arch->name);
1098  update_ob_speed(op);
1099  continue;
1100  }
1101 
1102  if (op->map == NULL
1103  && op->env == NULL
1104  && op->name
1105  && op->type != MAP) {
1106  LOG(llevError, "BUG: process_events(): Object without map or inventory is on active list: %s (%d)\n", op->name, op->count);
1107  op->speed = 0;
1108  update_ob_speed(op);
1109  continue;
1110  }
1111 
1112  /* Seen some cases where process_object() is crashing because
1113  * the object is on a swapped out map. But can't be sure if
1114  * something in the chain of events caused the object to
1115  * change maps or was just never removed - this will
1116  * give some clue as to its state before call to
1117  * process_object
1118  */
1119  if (op->map && op->map->in_memory != MAP_IN_MEMORY) {
1120  LOG(llevError, "BUG: process_events(): Processing object on swapped out map: %s (%d), map=%s\n", op->name, op->count, op->map->path);
1121  }
1122 
1123  /* Animate the object. Bug of feature that andim_speed
1124  * is based on ticks, and not the creatures speed?
1125  */
1126  if ((op->anim_speed && op->last_anim >= op->anim_speed)
1127  || (op->temp_animation_id && op->last_anim >= op->temp_anim_speed)) {
1128  op->state++;
1129  if ((op->type == PLAYER) || (op->type == MONSTER))
1130  animate_object(op, op->facing);
1131  else
1132  animate_object(op, op->direction);
1133  op->last_anim = 1;
1134  } else {
1135  op->last_anim++;
1136  }
1137 
1138  if (op->speed_left > 0) {
1139  --op->speed_left;
1140  process_object(op);
1141  if (was_destroyed(op, tag))
1142  continue;
1143  }
1144  if (settings.casting_time == TRUE && op->casting_time > 0)
1145  op->casting_time--;
1146  if (op->speed_left <= 0)
1147  op->speed_left += FABS(op->speed);
1148  }
1149 
1150  /* Remove marker object from active list */
1151  if (marker.active_prev != NULL)
1152  marker.active_prev->active_next = NULL;
1153  else
1154  active_objects = NULL;
1155 
1156  process_players2();
1157 }
1158 
1164 void clean_tmp_files(void) {
1165  mapstruct *m, *next;
1166 
1167  LOG(llevInfo, "Cleaning up...\n");
1168 
1169  /* We save the maps - it may not be intuitive why, but if there are unique
1170  * items, we need to save the map so they get saved off. Perhaps we should
1171  * just make a special function that only saves the unique items.
1172  */
1173  for (m = first_map; m != NULL; m = next) {
1174  next = m->next;
1175  if (m->in_memory == MAP_IN_MEMORY) {
1176  /* If we want to reuse the temp maps, swap it out (note that will also
1177  * update the log file. Otherwise, save the map (mostly for unique item
1178  * stuff). Note that the clean_tmp_map is called after the end of
1179  * the for loop but is in the #else bracket. IF we are recycling the maps,
1180  * we certainly don't want the temp maps removed.
1181  */
1182 
1183  /* XXX The above comment is dead wrong */
1185  swap_map(m);
1186  else {
1187  save_map(m, SAVE_MODE_NORMAL); /* note we save here into a overlay map */
1188  clean_tmp_map(m);
1189  }
1190  }
1191  }
1192  write_todclock(); /* lets just write the clock here */
1193 }
1194 
1196 void cleanup(void) {
1197  LOG(llevDebug, "Cleanup called. freeing data.\n");
1198  clean_tmp_files();
1200 
1201 #ifdef MEMORY_DEBUG
1202  free_all_maps();
1203  free_style_maps();
1204 #endif
1205  cleanupPlugins();
1206 #ifdef MEMORY_DEBUG
1207  free_all_archs();
1209  free_all_images();
1211  free_all_recipes();
1213  free_all_god();
1214  free_all_anim();
1215  free_loader();
1216  free_globals();
1217  free_server();
1219  /* See what the string data that is out there that hasn't been freed. */
1220  /* LOG(llevDebug, "%s", ss_dump_table(0xff));*/
1221 #endif
1222  exit(0);
1223 }
1224 
1234 void leave(player *pl, int draw_exit) {
1235 
1236  if (pl != NULL) {
1237  pl->socket.status = Ns_Dead;
1238  LOG(llevInfo, "LOGOUT: Player named %s from ip %s\n", pl->ob->name, pl->socket.host);
1239 
1240  check_score(pl->ob, 1);
1241 
1242  /* If this player is the captain of the transport, need to do
1243  * some extra work. By the time we get here, remove_ob()
1244  * should have already been called.
1245  */
1246  if (pl->transport && pl->transport->contr == pl) {
1247  /* If inv is a non player, inv->contr will be NULL, but that
1248  * is OK.
1249  */
1250  if (pl->transport->inv)
1251  pl->transport->contr = pl->transport->inv->contr;
1252  else
1253  pl->transport->contr = NULL;
1254 
1255  if (pl->transport->contr) {
1256  char name[MAX_BUF];
1257 
1258  query_name(pl->transport, name, MAX_BUF);
1261  "%s has left. You are now the captain of %s",
1262  "%s has left. You are now the captain of %s",
1263  pl->ob->name, name);
1264  }
1265  }
1266 
1267  if (pl->ob->map) {
1268  if (pl->ob->map->in_memory == MAP_IN_MEMORY)
1269  pl->ob->map->timeout = MAP_TIMEOUT(pl->ob->map);
1270  /* we need to update player count, since remove_ob() isn't called */
1271  if (!pl->hidden)
1272  pl->ob->map->players--;
1273  pl->ob->map = NULL;
1274  }
1275  pl->ob->type = DEAD_OBJECT; /* To avoid problems with inventory window */
1276  }
1277  /* If a hidden dm dropped connection do not create
1278  * inconsistencies by showing that they have left the game
1279  */
1280  if (!(QUERY_FLAG(pl->ob, FLAG_WIZ) && pl->ob->contr->hidden)
1281  && (pl != NULL && draw_exit) && (pl->state != ST_GET_NAME && pl->state != ST_GET_PASSWORD && pl->state != ST_CONFIRM_PASSWORD))
1284  "%s left the game.",
1285  "%s left the game.",
1286  pl->ob->name);
1287 }
1288 
1296 int forbid_play(void) {
1297 #if !defined(_IBMR2) && !defined(___IBMR2) && defined(PERM_FILE)
1298  char buf[MAX_BUF], day[MAX_BUF];
1299  FILE *fp;
1300  time_t clock;
1301  struct tm *tm;
1302  int i, start, stop, forbit = 0, comp;
1303 
1304  clock = time(NULL);
1305  tm = (struct tm *)localtime(&clock);
1306 
1307  snprintf(buf, sizeof(buf), "%s/%s", settings.confdir, PERM_FILE);
1308  if ((fp = open_and_uncompress(buf, 0, &comp)) == NULL)
1309  return 0;
1310 
1311  while (fgets(buf, sizeof(buf), fp)) {
1312  if (buf[0] == '#')
1313  continue;
1314  if (!strncmp(buf, "msg", 3)) {
1315  if (forbit)
1316  while (fgets(buf, sizeof(buf), fp)) /* print message */
1317  fputs(buf, logfile);
1318  break;
1319  } else if (sscanf(buf, "%s %d%*c%d\n", day, &start, &stop) != 3) {
1320  LOG(llevDebug, "Warning: Incomplete line in permission file ignored.\n");
1321  continue;
1322  }
1323 
1324  for (i = 0; i < 7; i++) {
1325  if (!strncmp(buf, days[i], 3)
1326  && (tm->tm_wday == i)
1327  && (tm->tm_hour >= start)
1328  && (tm->tm_hour < stop))
1329  forbit = 1;
1330  }
1331  }
1332 
1333  close_and_delete(fp, comp);
1334 
1335  return forbit;
1336 #else
1337  return 0;
1338 #endif
1339 }
1340 
1341 extern unsigned long todtick;
1342 
1357 static void do_specials(void) {
1358 
1359 #ifdef WATCHDOG
1360  if (!(pticks%503))
1361  watchdog();
1362 #endif
1363 
1364  if (!(pticks%PTICKS_PER_CLOCK))
1365  tick_the_clock();
1366 
1367  if (!(pticks%509))
1368  flush_old_maps(); /* Clears the tmp-files of maps which have reset */
1369 
1370  if (!(pticks%2503))
1371  fix_weight(); /* Hack to fix weightproblems caused by bugs */
1372 
1373  if (!(pticks%2521))
1374  metaserver_update(); /* 2500 ticks is about 5 minutes */
1375 
1376  if (!(pticks%5003))
1378 
1379  if (!(pticks%5009))
1381 
1382  if (!(pticks%5011))
1383  obsolete_parties();
1384 
1385  if (!(pticks%12503))
1386  fix_luck();
1387 }
1388 
1399 int server_main(int argc, char **argv) {
1400 #ifdef WIN32 /* ---win32 this sets the win32 from 0d0a to 0a handling */
1401  _fmode = _O_BINARY;
1402  bRunning = 1;
1403 #endif
1404 
1405 #ifndef WIN32
1406  /* Here we check that we aren't root or suid */
1407  if (getuid() == 0 || geteuid() == 0) {
1408  fputs("Don't run crossfire as root, it is unsupported.\n", stderr);
1409  fputs("Instead run it as a normal unprivileged user.\n", stderr);
1410  fputs("Aborting...\n", stderr);
1411  return 1;
1412  }
1413 #endif
1414 
1415 #ifdef DEBUG_MALLOC_LEVEL
1416  malloc_debug(DEBUG_MALLOC_LEVEL);
1417 #endif
1418 
1419  settings.argc = argc;
1420  settings.argv = argv;
1421  init(argc, argv);
1422  initPlugins(); /* GROS - Init the Plugins */
1423 #ifdef WIN32
1424  while (bRunning) {
1425 #else
1426  for (;;) {
1427 #endif
1428  nroferrors = 0;
1429 
1430  do_server();
1431  process_events(); /* "do" something with objects with speed */
1432  cftimer_process_timers(); /* Process the crossfire Timers */
1433  /* Lauwenmark : Here we handle the CLOCK global event */
1435  check_active_maps(); /* Removes unused maps after a certain timeout */
1436  do_specials(); /* Routines called from time to time. */
1437 
1438  sleep_delta(); /* Sleep proper amount of time before next tick */
1439  }
1440  emergency_save(0);
1441  cleanup();
1442  return 0;
1443 }
void enter_exit(object *op, object *exit_ob)
Definition: server.c:740
EXTERN FILE * logfile
Definition: global.h:220
#define AP_UNAPPLY
Definition: define.h:1010
sint16 bed_x
Definition: player.h:152
char path[HUGE_BUF]
Definition: map.h:384
int find_dir_2(int x, int y)
Definition: object.c:3380
void free_all_maps(void)
Definition: map.c:1968
void leave(player *pl, int draw_exit)
Definition: server.c:1234
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, sint16 x, sint16 y, sint16 *nx, sint16 *ny)
Definition: map.c:330
Definition: player.h:146
uint16 emergency_y
Definition: global.h:389
#define FLAG_DAMNED
Definition: define.h:614
void do_server(void)
Definition: loop.c:383
#define DEAD_OBJECT
Definition: define.h:186
uint32 pticks
Definition: time.c:56
Definition: map.h:399
void enter_player_savebed(object *op)
Definition: server.c:175
void cleanup(void)
Definition: server.c:1196
static void enter_random_map(object *pl, object *exit_ob)
Definition: server.c:420
uint16 emergency_x
Definition: global.h:389
static void do_specials(void)
Definition: server.c:1357
#define NDI_ALL
Definition: newclient.h:220
#define FABS(x)
Definition: define.h:61
uint32 name_changed
Definition: player.h:184
mapstruct * generate_random_map(const char *OutFileName, RMParms *RP, char **use_layout)
Definition: random_map.c:80
uint8 recycle_tmp_maps
Definition: global.h:360
void do_some_living(object *op)
Definition: player.c:3017
void version(object *op)
Definition: server.c:81
void metaserver_update(void)
Definition: metaserver.c:134
object * insert_ob_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.c:1761
char final_map[RM_SIZE]
Definition: random_map.h:52
char * create_pathname(const char *name, char *buf, size_t size)
Definition: map.c:114
int save_player(object *op, int flag)
Definition: login.c:223
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:64
uint8 casting_time
Definition: global.h:358
mapstruct * ready_map_name(const char *name, int flags)
Definition: map.c:1809
const char * playerdir
Definition: global.h:336
#define MAP_ENTER_X(m)
Definition: map.h:104
void free_string(sstring str)
Definition: shstr.c:272
#define MAP
Definition: define.h:134
#define HUGE_BUF
Definition: define.h:83
#define EVENT_MAPLEAVE
Definition: plugin.h:87
sint16 players
Definition: map.h:365
#define MAP_HEIGHT(m)
Definition: map.h:99
object clone
Definition: object.h:326
socket_struct socket
Definition: player.h:148
short freearr_x[SIZEOFFREE]
Definition: object.c:75
uint8 last_anim
Definition: object.h:269
#define ST_CONFIRM_PASSWORD
Definition: define.h:893
#define MSG_TYPE_ADMIN_PLAYER
Definition: newclient.h:414
void draw_ext_info(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *message, const char *oldmessage)
Definition: standalone.c:171
const char * slaying
Definition: object.h:172
region * get_region_by_map(mapstruct *m)
Definition: region.c:85
object * ranges[range_size]
Definition: player.h:157
uint32 in_memory
Definition: map.h:366
#define AUTOSAVE
Definition: config.h:665
void swap_below_max(const char *except_level)
Definition: swap.c:253
char ** argv
Definition: global.h:332
void close_and_delete(FILE *fp, int compressed)
Definition: porting.c:748
mapstruct * load_original_map(const char *filename, int flags)
Definition: map.c:1226
enum Sock_Status status
Definition: newserver.h:116
#define PERM_FILE
Definition: config.h:503
#define SAVE_MODE_NORMAL
Definition: map.h:141
sint16 x
Definition: object.h:179
void remove_friendly_object(object *op)
Definition: friend.c:69
method_ret ob_apply(object *op, object *applier, int aflags)
Definition: ob_methods.c:59
void fix_weight(void)
Definition: player.c:3645
void clean_friendly_list(void)
Definition: friend.c:124
uint8 temp_anim_speed
Definition: object.h:271
void draw_ext_info_format(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *new_format, const char *old_format,...)
Definition: standalone.c:175
static void enter_unique_map(object *op, object *exit_ob)
Definition: server.c:654
struct obj * enemy
Definition: object.h:232
sint8 sounds_this_tick
Definition: newserver.h:148
int swap_map(mapstruct *map)
Definition: swap.c:146
#define ST_PLAYING
Definition: define.h:886
char savebed_map[MAX_BUF]
Definition: player.h:151
#define NDI_DK_ORANGE
Definition: newclient.h:201
char * host
Definition: newserver.h:125
static const char days[7][4]
Definition: server.c:65
#define PLAYER
Definition: define.h:113
#define MSG_TYPE_COMMAND_FAILURE
Definition: newclient.h:449
#define FLAG_REMOVED
Definition: define.h:528
void check_active_maps(void)
Definition: swap.c:206
sint32 timeout
Definition: map.h:362
short freearr_y[SIZEOFFREE]
Definition: object.c:81
object * active_objects
Definition: object.c:72
void free_all_newserver(void)
Definition: init.c:292
void map_newmap_cmd(socket_struct *ns)
Definition: request.c:672
int forbid_play(void)
Definition: server.c:1296
char * name
Definition: map.h:349
uint32 tag_t
Definition: object.h:40
#define MAP_IN_MEMORY
Definition: map.h:151
void remove_ob(object *op)
Definition: object.c:1515
void flush_old_maps(void)
Definition: swap.c:305
void free_loader(void)
int argc
Definition: global.h:331
#define EVENT_MAPENTER
Definition: plugin.h:86
void write_todclock(void)
Definition: init.c:424
void fix_auto_apply(mapstruct *m)
Definition: standalone.c:130
uint32 golem_count
Definition: player.h:160
static char * clean_path(const char *file, char *newpath, int size)
Definition: server.c:366
float speed_left
Definition: object.h:182
uint32 hidden
Definition: player.h:186
static void enter_fixed_template_map(object *pl, object *exit_ob)
Definition: server.c:489
void send_background_music(player *pl, const char *music)
Definition: sounds.c:121
void free_all_treasures(void)
Definition: treasure.c:2131
unsigned long todtick
Definition: init.c:418
struct mapdef * map
Definition: object.h:155
static void enter_random_template_map(object *pl, object *exit_ob)
Definition: server.c:586
void get_rangevector(object *op1, const object *op2, rv_vector *retval, int flags)
Definition: map.c:2504
struct obj * active_prev
Definition: object.h:141
void dump_object(object *op, StringBuffer *sb)
Definition: object.c:372
void free_all_anim(void)
Definition: anim.c:41
object * transport
Definition: player.h:249
#define MAP_TIMEOUT(m)
Definition: map.h:85
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
Definition: path.c:184
float weapon_sp
Definition: player.h:194
sint16 dam
Definition: living.h:87
uint16 temp_animation_id
Definition: object.h:270
const char * name
Definition: object.h:167
struct obj * env
Definition: object.h:151
uint8 state
Definition: player.h:172
struct obj * below
Definition: object.h:145
int execute_global_event(int eventcode,...)
Definition: standalone.c:229
#define EXIT_PATH(xyz)
Definition: define.h:748
#define INS_NO_WALK_ON
Definition: object.h:396
static void process_players1(void)
Definition: server.c:908
#define TRUE
Definition: exp.c:41
#define MAP_MAXTIMEOUT
Definition: config.h:412
#define MAP_ENTER_Y(m)
Definition: map.h:106
static char * unclean_path(const char *src, char *newpath, int size)
Definition: server.c:394
void check_score(object *op, int quiet)
Definition: hiscore.c:289
EXTERN long nroferrors
Definition: global.h:212
#define SIZEOFFREE
Definition: define.h:441
int bRunning
Definition: win32.c:202
#define EXIT_X(xyz)
Definition: define.h:750
sint8 facing
Definition: object.h:186
sint16 y
Definition: object.h:179
struct pl * contr
Definition: object.h:134
void obsolete_parties(void)
Definition: c_party.c:165
#define MSG_TYPE_ADMIN_VERSION
Definition: newclient.h:419
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:283
void free_globals(void)
Definition: init.c:307
void remove_all_pets(void)
Definition: pets.c:273
void process_events(void)
Definition: server.c:1026
void tick_the_clock(void)
Definition: weather.c:111
uint32 count
Definition: player.h:163
float speed
Definition: object.h:181
int process_object(object *op)
Definition: time.c:724
void init(int argc, char **argv)
Definition: init.c:905
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
uint8 state
Definition: object.h:200
void cleanupPlugins(void)
Definition: plugins.c:4623
int server_main(int argc, char **argv)
Definition: server.c:1399
void fix_luck(void)
Definition: player.c:3661
void emergency_save(int flag)
Definition: standalone.c:191
#define FLAG_WIZ
Definition: define.h:527
void clean_tmp_files(void)
Definition: server.c:1164
#define MAP_MINTIMEOUT
Definition: config.h:414
#define EXIT_Y(xyz)
Definition: define.h:751
#define MAX_BUF
Definition: define.h:81
#define MSG_TYPE_ADMIN
Definition: newclient.h:324
struct obj * active_next
Definition: object.h:137
object * get_object(void)
Definition: object.c:921
void free_all_images(void)
Definition: image.c:418
object * insert_ob_in_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.c:1992
void free_all_archs(void)
Definition: arch.c:298
int Ysize
Definition: random_map.h:60
int handle_newcs_player(object *op)
Definition: player.c:2826
#define MSG_TYPE_ADMIN_DM
Definition: newclient.h:415
const char * confdir
Definition: global.h:333
static const flag_definition flags[]
int Xsize
Definition: random_map.h:59
char * crypt_string(char *str, char *salt)
Definition: server.c:130
void animate_object(object *op, int dir)
Definition: anim.c:186
int save_map(mapstruct *m, int flag)
Definition: map.c:1453
void free_all_recipes(void)
Definition: recipe.c:721
object * ob
Definition: player.h:207
uint32 unique
Definition: map.h:358
char origin_map[RM_SIZE]
Definition: random_map.h:51
#define EVENT_CLOCK
Definition: plugin.h:80
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
sint16 bed_y
Definition: player.h:152
uint32 is_template
Definition: map.h:359
#define FORCE
Definition: define.h:296
void replace(const char *src, const char *key, const char *replacement, char *result, size_t resultsize)
Definition: utils.c:444
uint32 attacktype
Definition: object.h:193
sint8 direction
Definition: object.h:185
int set_random_map_variable(RMParms *rp, const char *buf)
int check_password(char *typed, char *crypted)
Definition: server.c:162
void sleep_delta(void)
Definition: time.c:195
#define PORTAL_DESTINATION_NAME
#define MAP_PLAYER_UNIQUE
Definition: map.h:117
const char * localdir
Definition: global.h:335
int origin_y
Definition: random_map.h:73
tag_t count
Definition: object.h:157
living stats
Definition: object.h:219
struct archt * arch
Definition: object.h:263
#define MAP_WIDTH(m)
Definition: map.h:97
unsigned int distance
Definition: map.h:400
struct Settings settings
Definition: init.c:48
static void enter_map(object *op, mapstruct *newmap, int x, int y)
Definition: server.c:215
struct regiondef * region
Definition: random_map.h:80
int out_of_map(mapstruct *m, int x, int y)
Definition: map.c:2300
void free_all_readable(void)
Definition: readable.c:2084
#define MSG_TYPE_COMMAND
Definition: newclient.h:326
#define SIZEOFFREE2
Definition: define.h:440
void cftimer_process_timers(void)
Definition: timers.c:53
const char * msg
Definition: object.h:175
sint16 casting_time
Definition: object.h:253
void write_book_archive(void)
Definition: readable.c:2127
#define MONSTER
Definition: define.h:261
void update_ob_speed(object *op)
Definition: object.c:1008
sstring add_string(const char *str)
Definition: shstr.c:116
EXTERN player * first_player
Definition: global.h:190
struct pl * next
Definition: player.h:147
int find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
Definition: object.c:3200
int initPlugins(void)
Definition: plugins.c:4588
uint8 anim_speed
Definition: object.h:268
void free_style_maps(void)
Definition: style.c:300
struct obj * inv
Definition: object.h:148
#define NDI_UNIQUE
Definition: newclient.h:219
#define SIZEOFFREE1
Definition: define.h:439
void watchdog(void)
char maplevel[MAX_BUF]
Definition: player.h:150
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63
void free_all_god(void)
Definition: holy.c:142
#define was_destroyed(op, old_tag)
Definition: object.h:94
#define FULL_VERSION
Definition: version.h:6
struct mapdef * next
Definition: map.h:347
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:628
#define VERSION
Definition: win32.h:16
void free_object(object *ob)
Definition: object.c:1238
char * emergency_mapname
Definition: global.h:388
Definition: map.h:346
char * background_music
Definition: map.h:386
void set_map_timeout(mapstruct *oldmap)
Definition: server.c:333
#define ST_GET_NAME
Definition: define.h:891
void free_server(void)
Definition: init.c:955
#define FLAG_UNIQUE
Definition: define.h:584
int origin_x
Definition: random_map.h:74
#define MSG_TYPE_ADMIN_LOGIN
Definition: newclient.h:418
void create_template_pathname(const char *name, char *buf, size_t size)
Definition: map.c:155
void free_all_object_data(void)
Definition: object.c:479
void clean_tmp_map(mapstruct *m)
Definition: map.c:1959
player * find_player_partial_name(const char *plname)
Definition: player.c:84
EXTERN mapstruct * first_map
Definition: global.h:191
struct obj * more
Definition: object.h:153
#define PTICKS_PER_CLOCK
Definition: tod.h:38
FILE * open_and_uncompress(const char *name, int flag, int *compressed)
Definition: porting.c:724
uint32 has_hit
Definition: player.h:183
void start_info(object *op)
Definition: server.c:97
sstring followed_player
Definition: player.h:253
const char * name
Definition: object.h:322
int hit_player(object *op, int dam, object *hitter, uint32 type, int full_hit)
Definition: attack.c:1868
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:78
#define P_NO_CLERIC
Definition: map.h:259
uint8 type
Definition: object.h:189
int ob_blocked(const object *ob, mapstruct *m, sint16 x, sint16 y)
Definition: map.c:525
#define ST_GET_PASSWORD
Definition: define.h:892
static void process_players2(void)
Definition: server.c:996
#define FLAG_FREED
Definition: define.h:529