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.37 by root, Tue Sep 12 20:55:40 2006 UTC vs.
Revision 1.46 by root, Thu Sep 14 21:16:11 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines