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.152 by root, Sun Apr 18 12:50:07 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 ob_locked 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 */
90 if (blocked (newmap, x, y)) 89 if (blocked (newmap, x, y))
91 { /* First choice blocked */ 90 { /* First choice blocked */
96 * Note that for the second and third calls, we could start at a position other 95 * Note that for the second and third calls, we could start at a position other
97 * than one, but then we could end up on the other side of walls and so forth. 96 * than one, but then we could end up on the other side of walls and so forth.
98 */ 97 */
99 int i = find_free_spot (this, newmap, x, y, 1, SIZEOFFREE1 + 1); 98 int i = find_free_spot (this, newmap, x, y, 1, SIZEOFFREE1 + 1);
100 99
101 if (i == -1) 100 if (i < 0)
102 { 101 {
103 i = find_free_spot (this, newmap, x, y, 1, SIZEOFFREE2 + 1); 102 i = find_free_spot (this, newmap, x, y, 1, SIZEOFFREE2 + 1);
104 if (i == -1) 103 if (i < 0)
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 != -1) 107 if (i >= 0)
108 {
109 maptile *m = newmap;
110 sint16 nx = x + DIRX (i);
111 sint16 ny = y + DIRY (i);
112
113 if (xy_normalise (m, nx, ny))
109 { 114 {
110 x += freearr_x[i]; 115 newmap = m;
111 y += freearr_y[i]; 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 this->x = x;
128 this->y = y;
129 map = newmap;
130
131 insert_ob_in_map (this, map, 0, INS_NO_WALK_ON);
132 133
133 enemy = 0; 134 enemy = 0;
134 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 {
135 if (contr) 143 if (contr)
136 { 144 {
137 contr->maplevel = newmap->path; 145 contr->maplevel = newmap->path;
138 contr->count = 0; 146 contr->count = 0;
139 }
140 147
141 /* Update any golems */ 148 /* Update any golems */
142 if (type == PLAYER)
143 if (object *golem = contr->golem) 149 if (object *golem = contr->golem)
144 { 150 {
145 int i = find_free_spot (golem, newmap, x, y, 1, SIZEOFFREE); 151 int i = find_free_spot (golem, newmap, x, y, 1, SIZEOFFREE);
146 152
147 if (i < 0) 153 if (i < 0)
148 golem->drop_and_destroy (); 154 golem->drop_and_destroy ();
149 else 155 else
150 { 156 {
151 newmap->insert (golem, x + freearr_x[i], y + freearr_y[i]); 157 newmap->insert (golem, x + DIRX (i), y + DIRY (i));
152 golem->direction = find_dir_2 (golem->x - x, golem->y - y); 158 golem->direction = find_dir_2 (golem->x - x, golem->y - y);
159 }
153 } 160 }
154 } 161 }
155 162
156 /* 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
157 * about pending objects. 164 * about pending objects.
158 */ 165 */
159 remove_all_pets (newmap); 166 move_all_pets ();
167
168 return true;
169 }
170
171 return false;
160} 172}
161 173
162/* process_players1 and process_players2 do all the player related stuff. 174/* process_players1 and process_players2 do all the player related stuff.
163 * 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
164 * 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
226 // used for the inner loop 238 // used for the inner loop
227 if (_i < actives.size ()) // HACK, rely on _i :/ 239 if (_i < actives.size ()) // HACK, rely on _i :/
228 { 240 {
229 object *next = actives [_i + 1]; 241 object *next = actives [_i + 1];
230 242
231 prefetch (&next->flag , 0, 1); 243 ecb_prefetch (&next->flag , 0, 1);
232 prefetch (&next->speed , 0, 1); 244 ecb_prefetch (&next->speed , 0, 1);
233 prefetch (&next->anim_speed, 0, 1); 245 ecb_prefetch (&next->anim_speed, 0, 1);
234 prefetch (&next->contr , 0, 1); 246 ecb_prefetch (&next->contr , 0, 1);
235 } 247 }
236 248
237 /* Now process op */ 249 /* Now process op */
238 if (expect_false (op->flag [FLAG_FREED])) 250 if (expect_false (op->flag [FLAG_FREED]))
239 { 251 {
240 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 ());
241 op->set_speed (0); 253 op->set_speed (0);
242 continue; 254 continue;
243 } 255 }
244 256
245 if (expect_false (!op->has_active_speed ())) 257 if (expect_false (!op->has_active_speed ()))
286 298
287/* clean up everything before exiting */ 299/* clean up everything before exiting */
288void 300void
289emergency_save () 301emergency_save ()
290{ 302{
291 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 ();
292 307
293 cfperl_emergency_save (); 308 cfperl_emergency_save ();
294 309
295 LOG (llevDebug, "saving book archive.\n");
296 write_book_archive ();
297
298 LOG (llevDebug, "emergency save done.\n"); 310 LOG (llevInfo, "emergency_save: leave\n");
299} 311}
300 312
301// send all clients some informational text 313// send all clients some informational text
302static void 314static void
303cleanup_inform (const char *cause, bool make_core) 315cleanup_inform (const char *cause, bool make_core)
322cleanup (const char *cause, bool make_core) 334cleanup (const char *cause, bool make_core)
323{ 335{
324 if (make_core) 336 if (make_core)
325 fork_abort (cause); 337 fork_abort (cause);
326 338
327 LOG (llevError, "cleanup cause: %s\n", cause); 339 LOG (make_core ? llevError : llevInfo, "cleanup cause: %s\n", cause);
328 340
329 if (!make_core) 341 if (!make_core)
330 cleanup_inform (cause, make_core); 342 cleanup_inform (cause, make_core);
331 343
332 LOG (llevDebug, "cleanup begin.\n"); 344 LOG (llevDebug, "cleanup begin.\n");
359 _exit (make_core); 371 _exit (make_core);
360} 372}
361 373
362/* 374/*
363 * 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.
364 * 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
365 * 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.
366 * 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
367 * 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
368 * 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
369 * 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
376do_specials () 388do_specials ()
377{ 389{
378 shstr::gc (); 390 shstr::gc ();
379 archetype::gc (); 391 archetype::gc ();
380 392
381 if (expect_false (!(pticks % TICKS_PER_HOUR))) 393 if (expect_false (!(server_tick % TICKS_PER_HOUR)))
382 maptile::adjust_daylight (); 394 maptile::adjust_daylight ();
383 395
384 if (expect_false (!(pticks % 2503))) 396 if (expect_false (!(server_tick % 2503)))
385 fix_weight (); /* Hack to fix weightproblems caused by bugs */ 397 fix_weight (); /* Hack to fix weightproblems caused by bugs */
386 398
387 if (expect_false (!(pticks % 5003))) 399 if (expect_false (!(server_tick % 5003)))
388 write_book_archive (); 400 write_book_archive ();
389 401
390 if (expect_false (!(pticks % 5009))) 402 if (expect_false (!(server_tick % 5009)))
391 clean_friendly_list (); 403 clean_friendly_list ();
392 404
393 if (expect_false (!(pticks % 5011))) 405 if (expect_false (!(server_tick % 5011)))
394 obsolete_parties (); 406 obsolete_parties ();
395 407
396 if (expect_false (!(pticks % 12503))) 408 if (expect_false (!(server_tick % 12503)))
397 fix_luck (); 409 fix_luck ();
398} 410}
399 411
400void 412void
401server_tick () 413one_tick ()
402{ 414{
403 // first do the user visible stuff 415 // first do the user visible stuff
404 INVOKE_GLOBAL (CLOCK); 416 INVOKE_GLOBAL (CLOCK);
405 process_events (); // "do" something with objects with speed 417 process_events (); // "do" something with objects with speed
406 client::clock (); // draw client maps etc. 418 client::clock (); // draw client maps etc.
407 419
408 // then do some bookkeeping, should not really be here 420 // then do some bookkeeping, should not really be here
409 do_specials (); /* Routines called from time to time. */ 421 do_specials (); /* Routines called from time to time. */
410 attachable::check_mortals (); 422 attachable::check_mortals ();
411 423
412 ++pticks; 424 // now that we aggressively reuse id's, this is very unlikely to happen...
413
414 if (object::object_count >= RESTART_COUNT) 425 if (object::object_count >= RESTART_COUNT)
415 cleanup ("running out of protocol ID values - need full restart"); 426 cleanup ("running out of protocol ID values - need full restart");
416} 427}
417 428
418// normal main 429// normal main
419int 430int
420main (int argc, char **argv) 431main (int argc, char **argv)
421{ 432{
422 settings.argc = argc; 433 settings.argc = argc;
423 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
424 460
425 rndm.seed (time (0));
426 g_thread_init (0); // for the slice allocator only
427
428 init (argc, argv); 461 init (argc, argv);
429 462
430 for (;;) 463 for (;;)
431 cfperl_main (); 464 cfperl_main ();
432} 465}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines