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.31 by root, Mon Sep 11 23:33:27 2006 UTC vs.
Revision 1.43 by root, Thu Sep 14 17:10:24 2006 UTC

29#include <stdio.h> 29#include <stdio.h>
30#include <sys/types.h> 30#include <sys/types.h>
31#include <sys/uio.h> 31#include <sys/uio.h>
32#include <object.h> 32#include <object.h>
33#include <funcpoint.h> 33#include <funcpoint.h>
34#include <skills.h>
35#include <loader.h> 34#include <loader.h>
36 35
37int nrofallocobjects = 0; 36int nrofallocobjects = 0;
37static UUID uuid;
38const uint64 UUID_SKIP = 1<<19;
38 39
39object *objects; /* Pointer to the list of used objects */ 40object *objects; /* Pointer to the list of used objects */
40object *active_objects; /* List of active objects that need to be processed */ 41object *active_objects; /* List of active objects that need to be processed */
41 42
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, 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,
50}; 51};
51int freedir[SIZEOFFREE] = { 52int freedir[SIZEOFFREE] = {
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, 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,
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 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
54}; 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}
55 133
56/* 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. */
57static int 135static int
58compare_ob_value_lists_one (const object *wants, const object *has) 136compare_ob_value_lists_one (const object *wants, const object *has)
59{ 137{
255 { 333 {
256 if (inv->inv) 334 if (inv->inv)
257 sum_weight (inv); 335 sum_weight (inv);
258 sum += inv->carrying + inv->weight * (inv->nrof ? inv->nrof : 1); 336 sum += inv->carrying + inv->weight * (inv->nrof ? inv->nrof : 1);
259 } 337 }
338
260 if (op->type == CONTAINER && op->stats.Str) 339 if (op->type == CONTAINER && op->stats.Str)
261 sum = (sum * (100 - op->stats.Str)) / 100; 340 sum = (sum * (100 - op->stats.Str)) / 100;
341
262 if (op->carrying != sum) 342 if (op->carrying != sum)
263 op->carrying = sum; 343 op->carrying = sum;
344
264 return sum; 345 return sum;
265} 346}
266 347
267/** 348/**
268 * Return the outermost environment object for a given object. 349 * Return the outermost environment object for a given object.
417 */ 498 */
418 499
419object * 500object *
420find_object_name (const char *str) 501find_object_name (const char *str)
421{ 502{
422 const char *name = shstr::find (str); 503 shstr_cmp str_ (str);
423 object *op; 504 object *op;
424 505
425 for (op = objects; op != NULL; op = op->next) 506 for (op = objects; op != NULL; op = op->next)
426 if (&op->name == name) 507 if (op->name == str_)
427 break; 508 break;
428 509
429 return op; 510 return op;
430} 511}
431 512
432void 513void
433free_all_object_data () 514free_all_object_data ()
434{ 515{
435 LOG (llevDebug, "%d allocated objects\n", nrofallocobjects); 516 LOG (llevDebug, "%d allocated objects\n", nrofallocobjects);
436}
437
438/*
439 * Returns the object which this object marks as being the owner.
440 * A id-scheme is used to avoid pointing to objects which have been
441 * freed and are now reused. If this is detected, the owner is
442 * set to NULL, and NULL is returned.
443 * Changed 2004-02-12 - if the player is setting at the play again
444 * prompt, he is removed, and we don't want to treat him as an owner of
445 * anything, so check removed flag. I don't expect that this should break
446 * anything - once an object is removed, it is basically dead anyways.
447 */
448object *
449object::get_owner ()
450{
451 if (!owner
452 || QUERY_FLAG (owner, FLAG_FREED)
453 || QUERY_FLAG (owner, FLAG_REMOVED))
454 owner = 0;
455
456 return owner;
457} 517}
458 518
459/* 519/*
460 * 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
461 * skill and experience objects. 521 * skill and experience objects.
531 591
532 /* What is not cleared is next, prev, and count */ 592 /* What is not cleared is next, prev, and count */
533 593
534 expmul = 1.0; 594 expmul = 1.0;
535 face = blank_face; 595 face = blank_face;
536 attacked_by_count = -1;
537 596
538 if (settings.casting_time) 597 if (settings.casting_time)
539 casting_time = -1; 598 casting_time = -1;
540} 599}
541 600
837 if (op->more != NULL) 896 if (op->more != NULL)
838 update_object (op->more, action); 897 update_object (op->more, action);
839} 898}
840 899
841static unordered_vector<object *> mortals; 900static unordered_vector<object *> mortals;
842static std::vector<object *> freed;
843 901
844void object::free_mortals () 902void object::free_mortals ()
845{ 903{
846 for (unordered_vector<object *>::iterator i = mortals.begin (); i != mortals.end ();) 904 for (unordered_vector<object *>::iterator i = mortals.begin (); i != mortals.end ();)
847 if ((*i)->refcnt) 905 if ((*i)->refcnt)
848 ++i; // further delay freeing 906 ++i; // further delay freeing
849 else 907 else
850 { 908 {
851 freed.push_back (*i);//D
852 //delete *i; 909 delete *i;
853 mortals.erase (i); 910 mortals.erase (i);
854 } 911 }
855 912
913 static int lastmortals = 0;//D
914
856 if (mortals.size())//D 915 if (mortals.size() != lastmortals)//D
916 {
917 lastmortals = mortals.size ();//D
857 LOG (llevDebug, "%d objects in mortal queue\n", mortals.size());//D 918 LOG (llevDebug, "%d objects in mortal queue\n", lastmortals);//D
919 }
858} 920}
859 921
860object::object () 922object::object ()
861{ 923{
862 SET_FLAG (this, FLAG_REMOVED); 924 SET_FLAG (this, FLAG_REMOVED);
863 925
864 expmul = 1.0; 926 expmul = 1.0;
865 face = blank_face; 927 face = blank_face;
866 attacked_by_count = -1;
867} 928}
868 929
869object::~object () 930object::~object ()
870{ 931{
871 free_key_values (this); 932 free_key_values (this);
872} 933}
873 934
874void object::link () 935void object::link ()
875{ 936{
876 count = ++ob_count; 937 count = ++ob_count;
938 uuid = gen_uuid ();
877 939
878 prev = 0; 940 prev = 0;
879 next = objects; 941 next = objects;
880 942
881 if (objects) 943 if (objects)
884 objects = this; 946 objects = this;
885} 947}
886 948
887void object::unlink () 949void object::unlink ()
888{ 950{
889 count = 0; 951 //count = 0;//D
890 952 if (!prev && !next) return;//D
891 /* Remove this object from the list of used objects */
892 if (prev)
893 {
894 prev->next = next;
895 prev = 0;
896 }
897
898 if (next)
899 {
900 next->prev = prev;
901 next = 0;
902 }
903 953
904 if (this == objects) 954 if (this == objects)
905 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;
906} 963}
907 964
908object *object::create () 965object *object::create ()
909{ 966{
910 object *
911 op;
912
913 if (freed.empty ())
914 op = new object; 967 object *op = new object;
915 else
916 {
917 // highly annoying, but the only way to get it stable right now
918 op = freed.back ();
919 freed.pop_back ();
920 op->~object ();
921 new ((void *) op) object;
922 }
923
924 op->link (); 968 op->link ();
925 return op; 969 return op;
926} 970}
927 971
928/* 972/*
938void object::free (bool free_inventory) 982void object::free (bool free_inventory)
939{ 983{
940 if (QUERY_FLAG (this, FLAG_FREED)) 984 if (QUERY_FLAG (this, FLAG_FREED))
941 return; 985 return;
942 986
987 if (QUERY_FLAG (this, FLAG_FRIENDLY))
988 remove_friendly_object (this);
989
943 if (!QUERY_FLAG (this, FLAG_REMOVED)) 990 if (!QUERY_FLAG (this, FLAG_REMOVED))
944 remove_ob (this); 991 remove_ob (this);
945
946 if (QUERY_FLAG (this, FLAG_FRIENDLY))
947 remove_friendly_object (this);
948 992
949 SET_FLAG (this, FLAG_FREED); 993 SET_FLAG (this, FLAG_FREED);
950 994
951 if (more) 995 if (more)
952 { 996 {
958 { 1002 {
959 /* Only if the space blocks everything do we not process - 1003 /* Only if the space blocks everything do we not process -
960 * if some form of movement is allowed, let objects 1004 * if some form of movement is allowed, let objects
961 * drop on that space. 1005 * drop on that space.
962 */ 1006 */
963 if (free_inventory || !map || map->in_memory != MAP_IN_MEMORY || (GET_MAP_MOVE_BLOCK (map, x, y) == MOVE_ALL)) 1007 if (free_inventory || !map || map->in_memory != MAP_IN_MEMORY || GET_MAP_MOVE_BLOCK (map, x, y) == MOVE_ALL)
964 { 1008 {
965 object *op = inv; 1009 object *op = inv;
966 1010
967 while (op) 1011 while (op)
968 { 1012 {
1224 * This function goes through all objects below and including top, and 1268 * This function goes through all objects below and including top, and
1225 * merges op to the first matching object. 1269 * merges op to the first matching object.
1226 * If top is NULL, it is calculated. 1270 * If top is NULL, it is calculated.
1227 * Returns pointer to object if it succeded in the merge, otherwise NULL 1271 * Returns pointer to object if it succeded in the merge, otherwise NULL
1228 */ 1272 */
1229
1230object * 1273object *
1231merge_ob (object *op, object *top) 1274merge_ob (object *op, object *top)
1232{ 1275{
1233 if (!op->nrof) 1276 if (!op->nrof)
1234 return 0; 1277 return 0;
2655 2698
2656 if (tempfile == NULL) 2699 if (tempfile == NULL)
2657 { 2700 {
2658 LOG (llevError, "Error - Unable to access load object temp file\n"); 2701 LOG (llevError, "Error - Unable to access load object temp file\n");
2659 return NULL; 2702 return NULL;
2660 }; 2703 }
2704
2661 fprintf (tempfile, obstr); 2705 fprintf (tempfile, obstr);
2662 fclose (tempfile); 2706 fclose (tempfile);
2663 2707
2664 op = get_object (); 2708 op = get_object ();
2665 2709
2722 * The returned string is shared. 2766 * The returned string is shared.
2723 */ 2767 */
2724const char * 2768const char *
2725get_ob_key_value (const object *op, const char *const key) 2769get_ob_key_value (const object *op, const char *const key)
2726{ 2770{
2727 key_value * 2771 key_value *link;
2728 link; 2772 shstr_cmp canonical_key (key);
2729 const char *
2730 canonical_key;
2731 2773
2732 canonical_key = shstr::find (key);
2733
2734 if (canonical_key == NULL) 2774 if (!canonical_key)
2735 { 2775 {
2736 /* 1. There being a field named key on any object 2776 /* 1. There being a field named key on any object
2737 * implies there'd be a shared string to find. 2777 * implies there'd be a shared string to find.
2738 * 2. Since there isn't, no object has this field. 2778 * 2. Since there isn't, no object has this field.
2739 * 3. Therefore, *this* object doesn't have this field. 2779 * 3. Therefore, *this* object doesn't have this field.
2740 */ 2780 */
2741 return NULL; 2781 return 0;
2742 } 2782 }
2743 2783
2744 /* This is copied from get_ob_key_link() above - 2784 /* This is copied from get_ob_key_link() above -
2745 * only 4 lines, and saves the function call overhead. 2785 * only 4 lines, and saves the function call overhead.
2746 */ 2786 */
2747 for (link = op->key_values; link != NULL; link = link->next) 2787 for (link = op->key_values; link; link = link->next)
2748 {
2749 if (link->key == canonical_key) 2788 if (link->key == canonical_key)
2750 {
2751 return link->value; 2789 return link->value;
2752 } 2790
2753 }
2754 return NULL; 2791 return 0;
2755} 2792}
2756 2793
2757 2794
2758/* 2795/*
2759 * Updates the canonical_key in op to value. 2796 * Updates the canonical_key in op to value.
2845 shstr key_ (key); 2882 shstr key_ (key);
2846 2883
2847 return set_ob_key_value_s (op, key_, value, add_key); 2884 return set_ob_key_value_s (op, key_, value, add_key);
2848} 2885}
2849 2886
2887object::depth_iterator::depth_iterator (object *container)
2888: iterator_base (container)
2889{
2890 while (item->inv)
2891 item = item->inv;
2892}
2893
2850void 2894void
2851object::deep_iterator::next () 2895object::depth_iterator::next ()
2852{ 2896{
2853 if (item->inv)
2854 item = item->inv;
2855 else if (item->below) 2897 if (item->below)
2898 {
2856 item = item->below; 2899 item = item->below;
2900
2901 while (item->inv)
2902 item = item->inv;
2903 }
2857 else 2904 else
2858 item = item->env->below; 2905 item = item->env;
2859} 2906}
2907
2908// return a suitable string describing an objetc in enough detail to find it
2909const char *
2910object::debug_desc (char *info) const
2911{
2912 char info2[256 * 3];
2913 char *p = info;
2914
2915 p += snprintf (p, 256, "%d=\"%s%s%s\"",
2916 count,
2917 &name,
2918 title ? " " : "",
2919 title ? (const char *)title : "");
2920
2921 if (env)
2922 p += snprintf (p, 256, "(in %s)", env->debug_desc (info2));
2923
2924 if (map)
2925 p += snprintf (p, 256, "(on %s@%d+%d)", map->path, x, y);
2926
2927 return info;
2928}
2929
2930const char *
2931object::debug_desc () const
2932{
2933 static char info[256 * 3];
2934 return debug_desc (info);
2935}
2936

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines