ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/main.C
(Generate patch)

Comparing deliantra/server/server/main.C (file contents):
Revision 1.155 by root, Wed Apr 21 06:45:57 2010 UTC vs.
Revision 1.180 by root, Sat Nov 17 23:40:04 2018 UTC

1/* 1/*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2017,2018 Marc Alexander Lehmann / the Deliantra team
4 * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 5 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2001-2003 Mark Wedel & Crossfire Development Team 6 * Copyright (©) 2001-2003 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992 Frank Tore Johansen 7 * Copyright (©) 1992 Frank Tore Johansen
7 * 8 *
8 * Deliantra is free software: you can redistribute it and/or modify it under 9 * Deliantra is free software: you can redistribute it and/or modify it under
9 * the terms of the Affero GNU General Public License as published by the 10 * the terms of the Affero GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your 11 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version. 12 * option) any later version.
12 * 13 *
13 * This program is distributed in the hope that it will be useful, 14 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 17 * GNU General Public License for more details.
17 * 18 *
18 * You should have received a copy of the Affero GNU General Public License 19 * You should have received a copy of the Affero GNU General Public License
19 * and the GNU General Public License along with this program. If not, see 20 * and the GNU General Public License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>. 21 * <http://www.gnu.org/licenses/>.
21 * 22 *
22 * The authors can be reached via e-mail to <support@deliantra.net> 23 * The authors can be reached via e-mail to <support@deliantra.net>
23 */ 24 */
24 25
25#include <global.h> 26#include <global.h>
26#include <object.h> 27#include <object.h>
29#include <sproto.h> 30#include <sproto.h>
30#include <time.h> 31#include <time.h>
31 32
32#include <glib.h> 33#include <glib.h>
33 34
34#include <../random_maps/random_map.h> 35#include <rmg.h>
35#include <../random_maps/rproto.h> 36#include <rproto.h>
36#include "path.h" 37#include "path.h"
37 38
38void 39void
39version (object *op) 40version (object *op)
40{ 41{
41 new_draw_info_format (NDI_UNIQUE, 0, op, "This is Deliantra v%s", VERSION); 42 new_draw_info_format (NDI_UNIQUE, 0, op, "This is Deliantra v%s", VERSION);
42} 43}
43 44
44/* This is a basic little function to put the player back to his 45/* This is a basic little function to put the player back to his
45 * savebed. We do some error checking - its possible that the 46 * savebed.
46 * savebed map may no longer exist, so we make sure the player
47 * goes someplace.
48 */ 47 */
49void 48void
50enter_player_savebed (object *op) 49enter_player_savebed (object *op)
51{ 50{
52 op->player_goto (op->contr->savebed_map, op->contr->bed_x, op->contr->bed_y); 51 op->player_goto (op->contr->savebed_map, op->contr->bed_x, op->contr->bed_y);
57 * new map. map, x, y must be set. map is the map we are moving the 56 * new map. map, x, y must be set. map is the map we are moving the
58 * player to - it could be the map he just came from if the load failed for 57 * player to - it could be the map he just came from if the load failed for
59 * whatever reason. If default map coordinates are to be used, then 58 * whatever reason. If default map coordinates are to be used, then
60 * the function that calls this should figure them out. 59 * the function that calls this should figure them out.
61 */ 60 */
62void 61bool
63object::enter_map (maptile *newmap, int x, int y) 62object::enter_map (maptile *newmap, int x, int y)
64{ 63{
65 if (destroyed () || !newmap || newmap->in_memory != MAP_ACTIVE) 64 if (destroyed () || !newmap || !newmap->linkable ())
66 return; 65 return false;
67 66
68 if (out_of_map (newmap, x, y)) 67 if (out_of_map (newmap, x, y))
69 { 68 {
70 LOG (llevError, "enter_map: supplied coordinates are not within the map! (%s: %d, %d)\n", &newmap->path, x, y); 69 LOG (llevError, "enter_map: supplied coordinates are not within the map! (%s: %d, %d)\n", &newmap->path, x, y);
71 x = newmap->enter_x; 70 x = newmap->enter_x;
73 if (out_of_map (newmap, x, y)) 72 if (out_of_map (newmap, x, y))
74 { 73 {
75 LOG (llevError, "enter_map: map %s provides invalid default enter location (%d, %d) > (%d, %d)\n", 74 LOG (llevError, "enter_map: map %s provides invalid default enter location (%d, %d) > (%d, %d)\n",
76 &newmap->path, x, y, newmap->width, newmap->height); 75 &newmap->path, x, y, newmap->width, newmap->height);
77 new_draw_info (NDI_UNIQUE, 0, this, "The exit is closed"); 76 new_draw_info (NDI_UNIQUE, 0, this, "The exit is closed");
78 return; 77 return false;
79 } 78 }
80 } 79 }
81 80
82 if (contr && map != newmap && map) 81 if (contr && map != newmap && map)
83 if (INVOKE_MAP (LEAVE, map, ARG_PLAYER (contr))) 82 if (INVOKE_MAP (LEAVE, map, ARG_PLAYER (contr)))
84 return; 83 return false;
85 84
86 // remove, so stupid blocked does not trigger a failure 85 // remove, so stupid blocked does not trigger a failure
87 remove (); 86 remove ();
88 87
89 /* try to find a spot for the player */ 88 /* try to find a spot for the player */
105 i = find_free_spot (this, newmap, x, y, 1, SIZEOFFREE); 104 i = find_free_spot (this, newmap, x, y, 1, SIZEOFFREE);
106 } 105 }
107 106
108 if (i >= 0) 107 if (i >= 0)
109 { 108 {
110 x += freearr_x[i]; 109 maptile *m = newmap;
111 y += freearr_y[i]; 110 sint16 nx = x + DIRX (i);
111 sint16 ny = y + DIRY (i);
112
113 if (xy_normalise (m, nx, ny))
114 {
115 newmap = m;
116 x = nx;
117 y = ny;
118 }
112 } 119 }
113 else 120 else
114 /* not much we can do in this case. */ 121 /* not much we can do in this case. */
115 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); 122 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);
116 } 123 }
117 124
118 if (contr && map != newmap) 125 if (contr && map != newmap)
119 { 126 {
120 if (INVOKE_PLAYER (MAP_CHANGE, contr, ARG_MAP (newmap), ARG_INT (x), ARG_INT (y))) 127 if (INVOKE_PLAYER (MAP_CHANGE, contr, ARG_MAP (newmap), ARG_INT (x), ARG_INT (y)))
121 return; 128 return false;
122 129
123 if (INVOKE_MAP (ENTER, newmap, ARG_PLAYER (contr), ARG_INT (x), ARG_INT (y))) 130 if (INVOKE_MAP (ENTER, newmap, ARG_PLAYER (contr), ARG_INT (x), ARG_INT (y)))
124 return; 131 return false;
125 } 132 }
126
127 newmap->insert (this, x, y, 0, INS_NO_WALK_ON);
128 133
129 enemy = 0; 134 enemy = 0;
130 135
136 newmap->activate (); // workaround for activate activating everyhing on the map, includign the palyer on the {link} map
137 //newmap->insert (this, x, y);
138 newmap->insert (this, x, y, 0, INS_NO_AUTO_EXIT);
139 prefetch_surrounding_maps ();
140
141 if (map == newmap) // see if we actually arrived there - insert might trigger a teleport
142 {
131 if (contr) 143 if (contr)
132 { 144 {
133 contr->maplevel = newmap->path; 145 contr->maplevel = newmap->path;
134 contr->count = 0; 146 contr->count = 0;
135 }
136 147
137 /* Update any golems */ 148 /* Update any golems */
138 if (type == PLAYER)
139 if (object *golem = contr->golem) 149 if (object *golem = contr->golem)
140 { 150 {
141 int i = find_free_spot (golem, newmap, x, y, 1, SIZEOFFREE); 151 int i = find_free_spot (golem, newmap, x, y, 1, SIZEOFFREE);
142 152
143 if (i < 0) 153 if (i < 0)
144 golem->drop_and_destroy (); 154 golem->drop_and_destroy ();
145 else 155 else
146 { 156 {
147 newmap->insert (golem, x + freearr_x[i], y + freearr_y[i]); 157 newmap->insert (golem, x + DIRX (i), y + DIRY (i));
148 golem->direction = find_dir_2 (golem->x - x, golem->y - y); 158 golem->direction = find_dir_2 (golem->x - x, golem->y - y);
159 }
149 } 160 }
150 } 161 }
151 162
152 /* since the players map is already loaded, we don't need to worry 163 /* since the players map is already loaded, we don't need to worry
153 * about pending objects. 164 * about pending objects.
154 */ 165 */
155 remove_all_pets (newmap); 166 move_all_pets ();
167
168 return true;
169 }
170
171 return false;
156} 172}
157 173
158/* process_players1 and process_players2 do all the player related stuff. 174/* process_players1 and process_players2 do all the player related stuff.
159 * I moved it out of process events and process_map. This was to some 175 * I moved it out of process events and process_map. This was to some
160 * extent for debugging as well as to get a better idea of the time used 176 * extent for debugging as well as to get a better idea of the time used
222 // used for the inner loop 238 // used for the inner loop
223 if (_i < actives.size ()) // HACK, rely on _i :/ 239 if (_i < actives.size ()) // HACK, rely on _i :/
224 { 240 {
225 object *next = actives [_i + 1]; 241 object *next = actives [_i + 1];
226 242
227 prefetch (&next->flag , 0, 1); 243 ecb_prefetch (&next->flag , 0, 1);
228 prefetch (&next->speed , 0, 1); 244 ecb_prefetch (&next->speed , 0, 1);
229 prefetch (&next->anim_speed, 0, 1); 245 ecb_prefetch (&next->anim_speed, 0, 1);
230 prefetch (&next->contr , 0, 1); 246 ecb_prefetch (&next->contr , 0, 1);
231 } 247 }
232 248
233 /* Now process op */ 249 /* Now process op */
234 if (expect_false (op->flag [FLAG_FREED])) 250 if (expect_false (op->flag [FLAG_FREED]))
235 { 251 {
236 LOG (llevError, "BUG: process_events(): Free object on list\n"); 252 LOG (llevError, "BUG: process_events(): Free object on list (%s)\n", op->debug_desc ());
237 op->set_speed (0); 253 op->set_speed (0);
238 continue; 254 continue;
239 } 255 }
240 256
241 if (expect_false (!op->has_active_speed ())) 257 if (expect_false (!op->has_active_speed ()))
282 298
283/* clean up everything before exiting */ 299/* clean up everything before exiting */
284void 300void
285emergency_save () 301emergency_save ()
286{ 302{
287 LOG (llevDebug, "emergency save begin.\n"); 303 LOG (llevInfo, "emergency_save: enter\n");
304
305 LOG (llevInfo, "emergency_save: saving book archive\n");
306 write_book_archive ();
288 307
289 cfperl_emergency_save (); 308 cfperl_emergency_save ();
290 309
291 LOG (llevDebug, "saving book archive.\n");
292 write_book_archive ();
293
294 LOG (llevDebug, "emergency save done.\n"); 310 LOG (llevInfo, "emergency_save: leave\n");
295} 311}
296 312
297// send all clients some informational text 313// send all clients some informational text
298static void 314static void
299cleanup_inform (const char *cause, bool make_core) 315cleanup_inform (const char *cause, bool make_core)
318cleanup (const char *cause, bool make_core) 334cleanup (const char *cause, bool make_core)
319{ 335{
320 if (make_core) 336 if (make_core)
321 fork_abort (cause); 337 fork_abort (cause);
322 338
323 LOG (llevError, "cleanup cause: %s\n", cause); 339 LOG (make_core ? llevError : llevInfo, "cleanup cause: %s\n", cause);
324 340
325 if (!make_core) 341 if (!make_core)
326 cleanup_inform (cause, make_core); 342 cleanup_inform (cause, make_core);
327 343
328 LOG (llevDebug, "cleanup begin.\n"); 344 LOG (llevDebug, "cleanup begin.\n");
355 _exit (make_core); 371 _exit (make_core);
356} 372}
357 373
358/* 374/*
359 * do_specials() is a collection of functions to call from time to time. 375 * do_specials() is a collection of functions to call from time to time.
360 * Modified 2000-1-14 MSW to use the global pticks count to determine how 376 * Modified 2000-1-14 MSW to use the global server_tick count to determine how
361 * often to do things. This will allow us to spred them out more often. 377 * often to do things. This will allow us to spred them out more often.
362 * I use prime numbers for the factor count - in that way, it is less likely 378 * I use prime numbers for the factor count - in that way, it is less likely
363 * these actions will fall on the same tick (compared to say using 500/2500/15000 379 * these actions will fall on the same tick (compared to say using 500/2500/15000
364 * which would mean on that 15,000 tick count a whole bunch of stuff gets 380 * which would mean on that 15,000 tick count a whole bunch of stuff gets
365 * done). Of course, there can still be times where multiple specials are 381 * done). Of course, there can still be times where multiple specials are
372do_specials () 388do_specials ()
373{ 389{
374 shstr::gc (); 390 shstr::gc ();
375 archetype::gc (); 391 archetype::gc ();
376 392
377 if (expect_false (!(pticks % TICKS_PER_HOUR))) 393 if (expect_false (!(server_tick % TICKS_PER_HOUR)))
378 maptile::adjust_daylight (); 394 maptile::adjust_daylight ();
379 395
380 if (expect_false (!(pticks % 2503))) 396 if (expect_false (!(server_tick % 2503)))
381 fix_weight (); /* Hack to fix weightproblems caused by bugs */ 397 fix_weight (); /* Hack to fix weightproblems caused by bugs */
382 398
383 if (expect_false (!(pticks % 5003))) 399 if (expect_false (!(server_tick % 5003)))
384 write_book_archive (); 400 write_book_archive ();
385 401
386 if (expect_false (!(pticks % 5009))) 402 if (expect_false (!(server_tick % 5009)))
387 clean_friendly_list (); 403 clean_friendly_list ();
388 404
389 if (expect_false (!(pticks % 5011))) 405 if (expect_false (!(server_tick % 5011)))
390 obsolete_parties (); 406 obsolete_parties ();
391 407
392 if (expect_false (!(pticks % 12503))) 408 if (expect_false (!(server_tick % 12503)))
393 fix_luck (); 409 fix_luck ();
394} 410}
395 411
396void 412void
397server_tick () 413one_tick ()
398{ 414{
399 // first do the user visible stuff 415 // first do the user visible stuff
400 INVOKE_GLOBAL (CLOCK); 416 INVOKE_GLOBAL (CLOCK);
401 process_events (); // "do" something with objects with speed 417 process_events (); // "do" something with objects with speed
402 client::clock (); // draw client maps etc. 418 client::clock (); // draw client maps etc.
403 419
404 // then do some bookkeeping, should not really be here 420 // then do some bookkeeping, should not really be here
405 do_specials (); /* Routines called from time to time. */ 421 do_specials (); /* Routines called from time to time. */
406 attachable::check_mortals (); 422 attachable::check_mortals ();
407 423
408 ++pticks; 424 // now that we aggressively reuse id's, this is very unlikely to happen...
409
410 if (object::object_count >= RESTART_COUNT) 425 if (object::object_count >= RESTART_COUNT)
411 cleanup ("running out of protocol ID values - need full restart"); 426 cleanup ("running out of protocol ID values - need full restart");
412} 427}
413 428
414// normal main 429// normal main
415int 430int
416main (int argc, char **argv) 431main (int argc, char **argv)
417{ 432{
418 settings.argc = argc; 433 settings.argc = argc;
419 settings.argv = argv; 434 settings.argv = argv;
435
436 rndm.seed (time (0));
437
438 // temporary(?) testing hack
439 if (argc >= 2 && !strcmp (argv [1], "--noise"))
440 {
441 void noise_test ();
442 noise_test ();
443 exit (0);
444 }
445
446#if 0
447 // code sometiems used for timing benchmarks
448 random_number_generator<freeciv_random_generator> rng;
449 rng.seed(0);
450 for (int i = 0; i < 10; ++i)
451 printf ("%08x\n", rng.get_u32());
452 for (int i = 0; i < 1000000; ++i)
453 volatile int r = rng.get_u32 ();
454 cstamp s = stamp ();
455 for (int i = 0; i < 1000000; ++i)
456 volatile int r = rng.next ();
457 printf ("c %d\n", (int)measure (s));
458 exit (0);
459#endif
420 460
421 rndm.seed (time (0));
422 g_thread_init (0); // for the slice allocator only
423
424 init (argc, argv); 461 init (argc, argv);
425 462
426 for (;;) 463 for (;;)
427 cfperl_main (); 464 cfperl_main ();
428} 465}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines