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

Comparing deliantra/server/common/object.C (file contents):
Revision 1.38 by root, Wed Sep 13 01:09:24 2006 UTC vs.
Revision 1.47 by root, Thu Sep 14 22:33:59 2006 UTC

1
2/* 1/*
3 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
4 3
5 Copyright (C) 2001 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2001 Mark Wedel & Crossfire Development Team
6 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
17 16
18 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 20
22 The authors can be reached via e-mail at crossfire-devel@real-time.com 21 The authors can be reached via e-mail at <crossfire@schmorp.de>
23*/ 22*/
24 23
25/* Eneq(@csd.uu.se): Added weight-modifiers in environment of objects. 24/* Eneq(@csd.uu.se): Added weight-modifiers in environment of objects.
26 sub/add_weight will transcend the environment updating the carrying 25 sub/add_weight will transcend the environment updating the carrying
27 variable. */ 26 variable. */
32#include <object.h> 31#include <object.h>
33#include <funcpoint.h> 32#include <funcpoint.h>
34#include <loader.h> 33#include <loader.h>
35 34
36int nrofallocobjects = 0; 35int nrofallocobjects = 0;
36static UUID uuid;
37const uint64 UUID_SKIP = 1<<19;
37 38
38object *objects; /* Pointer to the list of used objects */
39object *active_objects; /* List of active objects that need to be processed */ 39object *active_objects; /* List of active objects that need to be processed */
40 40
41short freearr_x[SIZEOFFREE] = { 0, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2, -2, -2, -2, -1, 41short freearr_x[SIZEOFFREE] = { 0, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2, -2, -2, -2, -1,
42 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3, -3, -3, -3, -3, -2, -1 42 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3, -3, -3, -3, -3, -2, -1
43}; 43};
49}; 49};
50int freedir[SIZEOFFREE] = { 50int freedir[SIZEOFFREE] = {
51 0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 2, 2, 3, 4, 4, 4, 5, 6, 6, 6, 7, 8, 8, 8, 51 0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 2, 2, 3, 4, 4, 4, 5, 6, 6, 6, 7, 8, 8, 8,
52 1, 2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 7, 8, 8, 8, 8, 8 52 1, 2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 7, 8, 8, 8, 8, 8
53}; 53};
54
55static void
56write_uuid (void)
57{
58 char filename1[MAX_BUF], filename2[MAX_BUF];
59
60 sprintf (filename1, "%s/uuid", settings.localdir);
61 sprintf (filename2, "%s/uuid~", settings.localdir);
62
63 FILE *fp;
64
65 if (!(fp = fopen (filename2, "w")))
66 {
67 LOG (llevError, "ERROR: cannot open %s for writing, unable to write UUID!\n", filename2);
68 return;
69 }
70
71 fprintf (fp, "<1,%llx>\n", (unsigned long long)uuid.seq + UUID_SKIP * 2);
72 fclose (fp);
73 rename (filename2, filename1);
74}
75
76static void
77read_uuid (void)
78{
79 char filename[MAX_BUF];
80
81 sprintf (filename, "%s/uuid", settings.localdir);
82
83 FILE *fp;
84
85 if (!(fp = fopen (filename, "r")))
86 {
87 if (errno == ENOENT)
88 {
89 LOG (llevInfo, "RESET uid to 1\n");
90 uuid.seq = 0;
91 write_uuid ();
92 return;
93 }
94
95 LOG (llevError, "FATAL: cannot open %s for reading!\n", filename);
96 _exit (1);
97 }
98
99 int version;
100 unsigned long long uid;
101 if (2 != fscanf (fp, "<%d,%llx>\n", &version, &uid) || version != 1)
102 {
103 LOG (llevError, "FATAL: error reading uid from %s!\n", filename);
104 _exit (1);
105 }
106
107 uuid.seq = uid;
108 write_uuid ();
109 LOG (llevDebug, "read UID: %lld\n", uid);
110 fclose (fp);
111}
112
113UUID
114gen_uuid ()
115{
116 UUID uid;
117
118 uid.seq = ++uuid.seq;
119
120 if (!(uuid.seq & (UUID_SKIP - 1)))
121 write_uuid ();
122
123 return uid;
124}
125
126void
127init_uuid ()
128{
129 read_uuid ();
130}
54 131
55/* Returns TRUE if every key_values in wants has a partner with the same value in has. */ 132/* Returns TRUE if every key_values in wants has a partner with the same value in has. */
56static int 133static int
57compare_ob_value_lists_one (const object *wants, const object *has) 134compare_ob_value_lists_one (const object *wants, const object *has)
58{ 135{
368void 445void
369dump_all_objects (void) 446dump_all_objects (void)
370{ 447{
371 object *op; 448 object *op;
372 449
373 for (op = objects; op != NULL; op = op->next) 450 for (op = object::first; op != NULL; op = op->next)
374 { 451 {
375 dump_object (op); 452 dump_object (op);
376 fprintf (logfile, "Object %d\n:%s\n", op->count, errmsg); 453 fprintf (logfile, "Object %d\n:%s\n", op->count, errmsg);
377 } 454 }
378} 455}
404object * 481object *
405find_object (tag_t i) 482find_object (tag_t i)
406{ 483{
407 object *op; 484 object *op;
408 485
409 for (op = objects; op != NULL; op = op->next) 486 for (op = object::first; op != NULL; op = op->next)
410 if (op->count == i) 487 if (op->count == i)
411 break; 488 break;
412 return op; 489 return op;
413} 490}
414 491
422find_object_name (const char *str) 499find_object_name (const char *str)
423{ 500{
424 shstr_cmp str_ (str); 501 shstr_cmp str_ (str);
425 object *op; 502 object *op;
426 503
427 for (op = objects; op != NULL; op = op->next) 504 for (op = object::first; op != NULL; op = op->next)
428 if (op->name == str_) 505 if (op->name == str_)
429 break; 506 break;
430 507
431 return op; 508 return op;
432} 509}
433 510
434void 511void
435free_all_object_data () 512free_all_object_data ()
436{ 513{
437 LOG (llevDebug, "%d allocated objects\n", nrofallocobjects); 514 LOG (llevDebug, "%d allocated objects\n", nrofallocobjects);
438}
439
440/*
441 * Returns the object which this object marks as being the owner.
442 * A id-scheme is used to avoid pointing to objects which have been
443 * freed and are now reused. If this is detected, the owner is
444 * set to NULL, and NULL is returned.
445 * Changed 2004-02-12 - if the player is setting at the play again
446 * prompt, he is removed, and we don't want to treat him as an owner of
447 * anything, so check removed flag. I don't expect that this should break
448 * anything - once an object is removed, it is basically dead anyways.
449 */
450object *
451object::get_owner ()
452{
453 if (!owner
454 || QUERY_FLAG (owner, FLAG_FREED)
455 || QUERY_FLAG (owner, FLAG_REMOVED))
456 owner = 0;
457
458 return owner;
459} 515}
460 516
461/* 517/*
462 * Sets the owner and sets the skill and exp pointers to owner's current 518 * Sets the owner and sets the skill and exp pointers to owner's current
463 * skill and experience objects. 519 * skill and experience objects.
533 589
534 /* What is not cleared is next, prev, and count */ 590 /* What is not cleared is next, prev, and count */
535 591
536 expmul = 1.0; 592 expmul = 1.0;
537 face = blank_face; 593 face = blank_face;
538 attacked_by_count = -1;
539 594
540 if (settings.casting_time) 595 if (settings.casting_time)
541 casting_time = -1; 596 casting_time = -1;
542} 597}
543 598
838 893
839 if (op->more != NULL) 894 if (op->more != NULL)
840 update_object (op->more, action); 895 update_object (op->more, action);
841} 896}
842 897
843static unordered_vector<object *> mortals; 898object::vector object::mortals;
844static std::vector<object *, slice_allocator <object *> > freed; 899object::vector object::objects; // not yet used
900object *object::first;
845 901
846void object::free_mortals () 902void object::free_mortals ()
847{ 903{
848 for (unordered_vector<object *>::iterator i = mortals.begin (); i != mortals.end ();) 904 for (AUTODECL (i, mortals.begin ()); i != mortals.end ();)
849 if ((*i)->refcnt) 905 if ((*i)->refcnt)
850 ++i; // further delay freeing 906 ++i; // further delay freeing
851 else 907 else
852 { 908 {
853 freed.push_back (*i);//D
854 //delete *i; 909 delete *i;
855 mortals.erase (i); 910 mortals.erase (i);
856 } 911 }
857 912
858 if (mortals.size() && 0)//D 913 static int lastmortals = 0;//D
914
915 if (mortals.size() != lastmortals)//D
916 {
917 lastmortals = mortals.size ();//D
859 LOG (llevDebug, "%d objects in mortal queue\n", mortals.size());//D 918 LOG (llevDebug, "%d objects in mortal queue\n", lastmortals);//D
919 }
860} 920}
861 921
862object::object () 922object::object ()
863{ 923{
864 SET_FLAG (this, FLAG_REMOVED); 924 SET_FLAG (this, FLAG_REMOVED);
865 925
866 expmul = 1.0; 926 expmul = 1.0;
867 face = blank_face; 927 face = blank_face;
868 attacked_by_count = -1;
869} 928}
870 929
871object::~object () 930object::~object ()
872{ 931{
873 free_key_values (this); 932 free_key_values (this);
874} 933}
875 934
876void object::link () 935void object::link ()
877{ 936{
878 count = ++ob_count; 937 count = ++ob_count;
938 uuid = gen_uuid ();
879 939
880 prev = 0; 940 prev = 0;
881 next = objects; 941 next = object::first;
882 942
883 if (objects) 943 if (object::first)
884 objects->prev = this; 944 object::first->prev = this;
885 945
886 objects = this; 946 object::first = this;
887} 947}
888 948
889void object::unlink () 949void object::unlink ()
890{ 950{
891 count = 0; 951 //count = 0;//D
952 if (!prev && !next) return;//D
892 953
893 if (this == objects) 954 if (this == object::first)
894 objects = next; 955 object::first = next;
895 956
896 /* Remove this object from the list of used objects */ 957 /* Remove this object from the list of used objects */
897 if (prev)
898 {
899 prev->next = next; 958 if (prev) prev->next = next;
959 if (next) next->prev = prev;
960
900 prev = 0; 961 prev = 0;
901 }
902
903 if (next)
904 {
905 next->prev = prev;
906 next = 0; 962 next = 0;
907 }
908} 963}
909 964
910object *object::create () 965object *object::create ()
911{ 966{
912 object *op;
913
914 if (freed.empty ())
915 op = new object; 967 object *op = new object;
916 else
917 {
918 // highly annoying, but the only way to get it stable right now
919 op = freed.back ();
920 freed.pop_back ();
921 op->~object ();
922 new ((void *) op) object;
923 }
924
925 op->link (); 968 op->link ();
926 return op; 969 return op;
927} 970}
928 971
929/* 972/*
995 op = tmp; 1038 op = tmp;
996 } 1039 }
997 } 1040 }
998 } 1041 }
999 1042
1043 // clear those pointers that likely might have circular references to us
1000 owner = 0; 1044 owner = 0;
1045 enemy = 0;
1046 attacked_by = 0;
1001 1047
1002 /* Remove object from the active list */ 1048 /* Remove object from the active list */
1003 speed = 0; 1049 speed = 0;
1004 update_ob_speed (this); 1050 update_ob_speed (this);
1005 1051
1017sub_weight (object *op, signed long weight) 1063sub_weight (object *op, signed long weight)
1018{ 1064{
1019 while (op != NULL) 1065 while (op != NULL)
1020 { 1066 {
1021 if (op->type == CONTAINER) 1067 if (op->type == CONTAINER)
1022 {
1023 weight = (signed long) (weight * (100 - op->stats.Str) / 100); 1068 weight = (signed long) (weight * (100 - op->stats.Str) / 100);
1024 } 1069
1025 op->carrying -= weight; 1070 op->carrying -= weight;
1026 op = op->env; 1071 op = op->env;
1027 } 1072 }
1028} 1073}
1029 1074
1037 */ 1082 */
1038 1083
1039void 1084void
1040remove_ob (object *op) 1085remove_ob (object *op)
1041{ 1086{
1087 object *tmp, *last = 0;
1042 object * 1088 object *otmp;
1043 tmp, *
1044 last = NULL;
1045 object *
1046 otmp;
1047 1089
1048 tag_t 1090 tag_t tag;
1049 tag;
1050 int
1051 check_walk_off; 1091 int check_walk_off;
1052 mapstruct * 1092 mapstruct *m;
1053 m;
1054 1093
1055 sint16 1094 sint16 x, y;
1056 x,
1057 y;
1058 1095
1059 if (QUERY_FLAG (op, FLAG_REMOVED)) 1096 if (QUERY_FLAG (op, FLAG_REMOVED))
1060 return; 1097 return;
1061 1098
1062 SET_FLAG (op, FLAG_REMOVED); 1099 SET_FLAG (op, FLAG_REMOVED);
1250 free_object (op); 1287 free_object (op);
1251 return top; 1288 return top;
1252 } 1289 }
1253 } 1290 }
1254 1291
1255 return NULL; 1292 return 0;
1256} 1293}
1257 1294
1258/* 1295/*
1259 * same as insert_ob_in_map except it handle separate coordinates and do a clean 1296 * same as insert_ob_in_map except it handle separate coordinates and do a clean
1260 * job preparing multi-part monsters 1297 * job preparing multi-part monsters
1587 remove_ob (tmp); 1624 remove_ob (tmp);
1588 free_object (tmp); 1625 free_object (tmp);
1589 } 1626 }
1590 } 1627 }
1591 1628
1592 tmp1 = arch_to_object (find_archetype (arch_string)); 1629 tmp1 = arch_to_object (archetype::find (arch_string));
1593 1630
1594 tmp1->x = op->x; 1631 tmp1->x = op->x;
1595 tmp1->y = op->y; 1632 tmp1->y = op->y;
1596 insert_ob_in_map (tmp1, op->map, op, 0); 1633 insert_ob_in_map (tmp1, op->map, op, 0);
1597} 1634}
2655 2692
2656 if (tempfile == NULL) 2693 if (tempfile == NULL)
2657 { 2694 {
2658 LOG (llevError, "Error - Unable to access load object temp file\n"); 2695 LOG (llevError, "Error - Unable to access load object temp file\n");
2659 return NULL; 2696 return NULL;
2660 }; 2697 }
2698
2661 fprintf (tempfile, obstr); 2699 fprintf (tempfile, obstr);
2662 fclose (tempfile); 2700 fclose (tempfile);
2663 2701
2664 op = get_object (); 2702 op = get_object ();
2665 2703

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines