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.33 by root, Tue Sep 12 00:53:56 2006 UTC vs.
Revision 1.44 by root, Thu Sep 14 17:29:27 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 */ 40object *objects; /* Pointer to the list of used objects */
39object *active_objects; /* List of active objects that need to be processed */ 41object *active_objects; /* List of active objects that need to be processed */
40 42
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, 43short 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,
49}; 51};
50int freedir[SIZEOFFREE] = { 52int 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, 53 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 54 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}; 55};
56
57static void
58write_uuid (void)
59{
60 char filename1[MAX_BUF], filename2[MAX_BUF];
61
62 sprintf (filename1, "%s/uuid", settings.localdir);
63 sprintf (filename2, "%s/uuid~", settings.localdir);
64
65 FILE *fp;
66
67 if (!(fp = fopen (filename2, "w")))
68 {
69 LOG (llevError, "ERROR: cannot open %s for writing, unable to write UUID!\n", filename2);
70 return;
71 }
72
73 fprintf (fp, "<1,%llx>\n", (unsigned long long)uuid.seq + UUID_SKIP * 2);
74 fclose (fp);
75 rename (filename2, filename1);
76}
77
78static void
79read_uuid (void)
80{
81 char filename[MAX_BUF];
82
83 sprintf (filename, "%s/uuid", settings.localdir);
84
85 FILE *fp;
86
87 if (!(fp = fopen (filename, "r")))
88 {
89 if (errno == ENOENT)
90 {
91 LOG (llevInfo, "RESET uid to 1\n");
92 uuid.seq = 0;
93 write_uuid ();
94 return;
95 }
96
97 LOG (llevError, "FATAL: cannot open %s for reading!\n", filename);
98 _exit (1);
99 }
100
101 int version;
102 unsigned long long uid;
103 if (2 != fscanf (fp, "<%d,%llx>\n", &version, &uid) || version != 1)
104 {
105 LOG (llevError, "FATAL: error reading uid from %s!\n", filename);
106 _exit (1);
107 }
108
109 uuid.seq = uid;
110 write_uuid ();
111 LOG (llevDebug, "read UID: %lld\n", uid);
112 fclose (fp);
113}
114
115UUID
116gen_uuid ()
117{
118 UUID uid;
119
120 uid.seq = ++uuid.seq;
121
122 if (!(uuid.seq & (UUID_SKIP - 1)))
123 write_uuid ();
124
125 return uid;
126}
127
128void
129init_uuid ()
130{
131 read_uuid ();
132}
54 133
55/* Returns TRUE if every key_values in wants has a partner with the same value in has. */ 134/* Returns TRUE if every key_values in wants has a partner with the same value in has. */
56static int 135static int
57compare_ob_value_lists_one (const object *wants, const object *has) 136compare_ob_value_lists_one (const object *wants, const object *has)
58{ 137{
254 { 333 {
255 if (inv->inv) 334 if (inv->inv)
256 sum_weight (inv); 335 sum_weight (inv);
257 sum += inv->carrying + inv->weight * (inv->nrof ? inv->nrof : 1); 336 sum += inv->carrying + inv->weight * (inv->nrof ? inv->nrof : 1);
258 } 337 }
338
259 if (op->type == CONTAINER && op->stats.Str) 339 if (op->type == CONTAINER && op->stats.Str)
260 sum = (sum * (100 - op->stats.Str)) / 100; 340 sum = (sum * (100 - op->stats.Str)) / 100;
341
261 if (op->carrying != sum) 342 if (op->carrying != sum)
262 op->carrying = sum; 343 op->carrying = sum;
344
263 return sum; 345 return sum;
264} 346}
265 347
266/** 348/**
267 * Return the outermost environment object for a given object. 349 * Return the outermost environment object for a given object.
416 */ 498 */
417 499
418object * 500object *
419find_object_name (const char *str) 501find_object_name (const char *str)
420{ 502{
421 const char *name = shstr::find (str); 503 shstr_cmp str_ (str);
422 object *op; 504 object *op;
423 505
424 for (op = objects; op != NULL; op = op->next) 506 for (op = objects; op != NULL; op = op->next)
425 if (&op->name == name) 507 if (op->name == str_)
426 break; 508 break;
427 509
428 return op; 510 return op;
429} 511}
430 512
431void 513void
432free_all_object_data () 514free_all_object_data ()
433{ 515{
434 LOG (llevDebug, "%d allocated objects\n", nrofallocobjects); 516 LOG (llevDebug, "%d allocated objects\n", nrofallocobjects);
435}
436
437/*
438 * Returns the object which this object marks as being the owner.
439 * A id-scheme is used to avoid pointing to objects which have been
440 * freed and are now reused. If this is detected, the owner is
441 * set to NULL, and NULL is returned.
442 * Changed 2004-02-12 - if the player is setting at the play again
443 * prompt, he is removed, and we don't want to treat him as an owner of
444 * anything, so check removed flag. I don't expect that this should break
445 * anything - once an object is removed, it is basically dead anyways.
446 */
447object *
448object::get_owner ()
449{
450 if (!owner
451 || QUERY_FLAG (owner, FLAG_FREED)
452 || QUERY_FLAG (owner, FLAG_REMOVED))
453 owner = 0;
454
455 return owner;
456} 517}
457 518
458/* 519/*
459 * Sets the owner and sets the skill and exp pointers to owner's current 520 * Sets the owner and sets the skill and exp pointers to owner's current
460 * skill and experience objects. 521 * skill and experience objects.
530 591
531 /* What is not cleared is next, prev, and count */ 592 /* What is not cleared is next, prev, and count */
532 593
533 expmul = 1.0; 594 expmul = 1.0;
534 face = blank_face; 595 face = blank_face;
535 attacked_by_count = -1;
536 596
537 if (settings.casting_time) 597 if (settings.casting_time)
538 casting_time = -1; 598 casting_time = -1;
539} 599}
540 600
836 if (op->more != NULL) 896 if (op->more != NULL)
837 update_object (op->more, action); 897 update_object (op->more, action);
838} 898}
839 899
840static unordered_vector<object *> mortals; 900static unordered_vector<object *> mortals;
841static std::vector<object *> freed;
842 901
843void object::free_mortals () 902void object::free_mortals ()
844{ 903{
845 for (unordered_vector<object *>::iterator i = mortals.begin (); i != mortals.end ();) 904 for (unordered_vector<object *>::iterator i = mortals.begin (); i != mortals.end ();)
846 if ((*i)->refcnt) 905 if ((*i)->refcnt)
847 ++i; // further delay freeing 906 ++i; // further delay freeing
848 else 907 else
849 { 908 {
850 freed.push_back (*i);//D
851 //delete *i; 909 delete *i;
852 mortals.erase (i); 910 mortals.erase (i);
853 } 911 }
854 912
913 static int lastmortals = 0;//D
914
855 if (mortals.size())//D 915 if (mortals.size() != lastmortals)//D
916 {
917 lastmortals = mortals.size ();//D
856 LOG (llevDebug, "%d objects in mortal queue\n", mortals.size());//D 918 LOG (llevDebug, "%d objects in mortal queue\n", lastmortals);//D
919 }
857} 920}
858 921
859object::object () 922object::object ()
860{ 923{
861 SET_FLAG (this, FLAG_REMOVED); 924 SET_FLAG (this, FLAG_REMOVED);
862 925
863 expmul = 1.0; 926 expmul = 1.0;
864 face = blank_face; 927 face = blank_face;
865 attacked_by_count = -1;
866} 928}
867 929
868object::~object () 930object::~object ()
869{ 931{
870 free_key_values (this); 932 free_key_values (this);
871} 933}
872 934
873void object::link () 935void object::link ()
874{ 936{
875 count = ++ob_count; 937 count = ++ob_count;
938 uuid = gen_uuid ();
876 939
877 prev = 0; 940 prev = 0;
878 next = objects; 941 next = objects;
879 942
880 if (objects) 943 if (objects)
883 objects = this; 946 objects = this;
884} 947}
885 948
886void object::unlink () 949void object::unlink ()
887{ 950{
888 count = 0; 951 //count = 0;//D
889 952 if (!prev && !next) return;//D
890 /* Remove this object from the list of used objects */
891 if (prev)
892 {
893 prev->next = next;
894 prev = 0;
895 }
896
897 if (next)
898 {
899 next->prev = prev;
900 next = 0;
901 }
902 953
903 if (this == objects) 954 if (this == objects)
904 objects = next; 955 objects = next;
956
957 /* Remove this object from the list of used objects */
958 if (prev) prev->next = next;
959 if (next) next->prev = prev;
960
961 prev = 0;
962 next = 0;
905} 963}
906 964
907object *object::create () 965object *object::create ()
908{ 966{
909 object *op;
910
911 if (freed.empty ())
912 op = new object; 967 object *op = new object;
913 else
914 {
915 // highly annoying, but the only way to get it stable right now
916 op = freed.back ();
917 freed.pop_back ();
918 op->~object ();
919 new ((void *) op) object;
920 }
921
922 op->link (); 968 op->link ();
923 return op; 969 return op;
924} 970}
925 971
926/* 972/*
992 op = tmp; 1038 op = tmp;
993 } 1039 }
994 } 1040 }
995 } 1041 }
996 1042
1043 // clear those pointers that likely might have circular references to us
997 owner = 0; 1044 owner = 0;
1045 enemy = 0;
1046 attacked_by = 0;
998 1047
999 /* Remove object from the active list */ 1048 /* Remove object from the active list */
1000 speed = 0; 1049 speed = 0;
1001 update_ob_speed (this); 1050 update_ob_speed (this);
1002 1051
1222 * This function goes through all objects below and including top, and 1271 * This function goes through all objects below and including top, and
1223 * merges op to the first matching object. 1272 * merges op to the first matching object.
1224 * If top is NULL, it is calculated. 1273 * If top is NULL, it is calculated.
1225 * Returns pointer to object if it succeded in the merge, otherwise NULL 1274 * Returns pointer to object if it succeded in the merge, otherwise NULL
1226 */ 1275 */
1227
1228object * 1276object *
1229merge_ob (object *op, object *top) 1277merge_ob (object *op, object *top)
1230{ 1278{
1231 if (!op->nrof) 1279 if (!op->nrof)
1232 return 0; 1280 return 0;
2653 2701
2654 if (tempfile == NULL) 2702 if (tempfile == NULL)
2655 { 2703 {
2656 LOG (llevError, "Error - Unable to access load object temp file\n"); 2704 LOG (llevError, "Error - Unable to access load object temp file\n");
2657 return NULL; 2705 return NULL;
2658 }; 2706 }
2707
2659 fprintf (tempfile, obstr); 2708 fprintf (tempfile, obstr);
2660 fclose (tempfile); 2709 fclose (tempfile);
2661 2710
2662 op = get_object (); 2711 op = get_object ();
2663 2712
2720 * The returned string is shared. 2769 * The returned string is shared.
2721 */ 2770 */
2722const char * 2771const char *
2723get_ob_key_value (const object *op, const char *const key) 2772get_ob_key_value (const object *op, const char *const key)
2724{ 2773{
2725 key_value * 2774 key_value *link;
2726 link; 2775 shstr_cmp canonical_key (key);
2727 const char *
2728 canonical_key;
2729 2776
2730 canonical_key = shstr::find (key);
2731
2732 if (canonical_key == NULL) 2777 if (!canonical_key)
2733 { 2778 {
2734 /* 1. There being a field named key on any object 2779 /* 1. There being a field named key on any object
2735 * implies there'd be a shared string to find. 2780 * implies there'd be a shared string to find.
2736 * 2. Since there isn't, no object has this field. 2781 * 2. Since there isn't, no object has this field.
2737 * 3. Therefore, *this* object doesn't have this field. 2782 * 3. Therefore, *this* object doesn't have this field.
2738 */ 2783 */
2739 return NULL; 2784 return 0;
2740 } 2785 }
2741 2786
2742 /* This is copied from get_ob_key_link() above - 2787 /* This is copied from get_ob_key_link() above -
2743 * only 4 lines, and saves the function call overhead. 2788 * only 4 lines, and saves the function call overhead.
2744 */ 2789 */
2745 for (link = op->key_values; link != NULL; link = link->next) 2790 for (link = op->key_values; link; link = link->next)
2746 {
2747 if (link->key == canonical_key) 2791 if (link->key == canonical_key)
2748 {
2749 return link->value; 2792 return link->value;
2750 } 2793
2751 }
2752 return NULL; 2794 return 0;
2753} 2795}
2754 2796
2755 2797
2756/* 2798/*
2757 * Updates the canonical_key in op to value. 2799 * Updates the canonical_key in op to value.
2843 shstr key_ (key); 2885 shstr key_ (key);
2844 2886
2845 return set_ob_key_value_s (op, key_, value, add_key); 2887 return set_ob_key_value_s (op, key_, value, add_key);
2846} 2888}
2847 2889
2890object::depth_iterator::depth_iterator (object *container)
2891: iterator_base (container)
2892{
2893 while (item->inv)
2894 item = item->inv;
2895}
2896
2848void 2897void
2849object::deep_iterator::next () 2898object::depth_iterator::next ()
2850{ 2899{
2851 if (item->inv)
2852 item = item->inv;
2853 else if (item->below) 2900 if (item->below)
2901 {
2854 item = item->below; 2902 item = item->below;
2903
2904 while (item->inv)
2905 item = item->inv;
2906 }
2855 else 2907 else
2856 item = item->env->below; 2908 item = item->env;
2857} 2909}
2910
2911// return a suitable string describing an objetc in enough detail to find it
2912const char *
2913object::debug_desc (char *info) const
2914{
2915 char info2[256 * 3];
2916 char *p = info;
2917
2918 p += snprintf (p, 256, "%d=\"%s%s%s\"",
2919 count,
2920 &name,
2921 title ? " " : "",
2922 title ? (const char *)title : "");
2923
2924 if (env)
2925 p += snprintf (p, 256, "(in %s)", env->debug_desc (info2));
2926
2927 if (map)
2928 p += snprintf (p, 256, "(on %s@%d+%d)", map->path, x, y);
2929
2930 return info;
2931}
2932
2933const char *
2934object::debug_desc () const
2935{
2936 static char info[256 * 3];
2937 return debug_desc (info);
2938}
2939

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines