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.32 by root, Mon Sep 11 23:53:30 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. */
29#include <stdio.h> 28#include <stdio.h>
30#include <sys/types.h> 29#include <sys/types.h>
31#include <sys/uio.h> 30#include <sys/uio.h>
32#include <object.h> 31#include <object.h>
33#include <funcpoint.h> 32#include <funcpoint.h>
34#include <skills.h>
35#include <loader.h> 33#include <loader.h>
36 34
37int nrofallocobjects = 0; 35int nrofallocobjects = 0;
36static UUID uuid;
37const uint64 UUID_SKIP = 1<<19;
38 38
39object *objects; /* Pointer to the list of used objects */
40object *active_objects; /* List of active objects that need to be processed */ 39object *active_objects; /* List of active objects that need to be processed */
41 40
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, 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,
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 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
44}; 43};
50}; 49};
51int freedir[SIZEOFFREE] = { 50int 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, 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 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
54}; 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}
55 131
56/* 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. */
57static int 133static int
58compare_ob_value_lists_one (const object *wants, const object *has) 134compare_ob_value_lists_one (const object *wants, const object *has)
59{ 135{
255 { 331 {
256 if (inv->inv) 332 if (inv->inv)
257 sum_weight (inv); 333 sum_weight (inv);
258 sum += inv->carrying + inv->weight * (inv->nrof ? inv->nrof : 1); 334 sum += inv->carrying + inv->weight * (inv->nrof ? inv->nrof : 1);
259 } 335 }
336
260 if (op->type == CONTAINER && op->stats.Str) 337 if (op->type == CONTAINER && op->stats.Str)
261 sum = (sum * (100 - op->stats.Str)) / 100; 338 sum = (sum * (100 - op->stats.Str)) / 100;
339
262 if (op->carrying != sum) 340 if (op->carrying != sum)
263 op->carrying = sum; 341 op->carrying = sum;
342
264 return sum; 343 return sum;
265} 344}
266 345
267/** 346/**
268 * Return the outermost environment object for a given object. 347 * Return the outermost environment object for a given object.
366void 445void
367dump_all_objects (void) 446dump_all_objects (void)
368{ 447{
369 object *op; 448 object *op;
370 449
371 for (op = objects; op != NULL; op = op->next) 450 for (op = object::first; op != NULL; op = op->next)
372 { 451 {
373 dump_object (op); 452 dump_object (op);
374 fprintf (logfile, "Object %d\n:%s\n", op->count, errmsg); 453 fprintf (logfile, "Object %d\n:%s\n", op->count, errmsg);
375 } 454 }
376} 455}
402object * 481object *
403find_object (tag_t i) 482find_object (tag_t i)
404{ 483{
405 object *op; 484 object *op;
406 485
407 for (op = objects; op != NULL; op = op->next) 486 for (op = object::first; op != NULL; op = op->next)
408 if (op->count == i) 487 if (op->count == i)
409 break; 488 break;
410 return op; 489 return op;
411} 490}
412 491
417 */ 496 */
418 497
419object * 498object *
420find_object_name (const char *str) 499find_object_name (const char *str)
421{ 500{
422 const char *name = shstr::find (str); 501 shstr_cmp str_ (str);
423 object *op; 502 object *op;
424 503
425 for (op = objects; op != NULL; op = op->next) 504 for (op = object::first; op != NULL; op = op->next)
426 if (&op->name == name) 505 if (op->name == str_)
427 break; 506 break;
428 507
429 return op; 508 return op;
430} 509}
431 510
432void 511void
433free_all_object_data () 512free_all_object_data ()
434{ 513{
435 LOG (llevDebug, "%d allocated objects\n", nrofallocobjects); 514 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} 515}
458 516
459/* 517/*
460 * 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
461 * skill and experience objects. 519 * skill and experience objects.
531 589
532 /* What is not cleared is next, prev, and count */ 590 /* What is not cleared is next, prev, and count */
533 591
534 expmul = 1.0; 592 expmul = 1.0;
535 face = blank_face; 593 face = blank_face;
536 attacked_by_count = -1;
537 594
538 if (settings.casting_time) 595 if (settings.casting_time)
539 casting_time = -1; 596 casting_time = -1;
540} 597}
541 598
836 893
837 if (op->more != NULL) 894 if (op->more != NULL)
838 update_object (op->more, action); 895 update_object (op->more, action);
839} 896}
840 897
841static unordered_vector<object *> mortals; 898object::vector object::mortals;
842static std::vector<object *> freed; 899object::vector object::objects; // not yet used
900object *object::first;
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 (AUTODECL (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 = object::first;
880 942
881 if (objects) 943 if (object::first)
882 objects->prev = this; 944 object::first->prev = this;
883 945
884 objects = this; 946 object::first = this;
885} 947}
886 948
887void object::unlink () 949void object::unlink ()
888{ 950{
889 count = 0; 951 //count = 0;//D
952 if (!prev && !next) return;//D
953
954 if (this == object::first)
955 object::first = next;
890 956
891 /* Remove this object from the list of used objects */ 957 /* Remove this object from the list of used objects */
892 if (prev)
893 {
894 prev->next = next; 958 if (prev) prev->next = next;
959 if (next) next->prev = prev;
960
895 prev = 0; 961 prev = 0;
896 }
897
898 if (next)
899 {
900 next->prev = prev;
901 next = 0; 962 next = 0;
902 }
903
904 if (this == objects)
905 objects = next;
906} 963}
907 964
908object *object::create () 965object *object::create ()
909{ 966{
910 object *op;
911
912 if (freed.empty ())
913 op = new object; 967 object *op = new object;
914 else
915 {
916 // highly annoying, but the only way to get it stable right now
917 op = freed.back ();
918 freed.pop_back ();
919 op->~object ();
920 new ((void *) op) object;
921 }
922
923 op->link (); 968 op->link ();
924 return op; 969 return op;
925} 970}
926 971
927/* 972/*
993 op = tmp; 1038 op = tmp;
994 } 1039 }
995 } 1040 }
996 } 1041 }
997 1042
1043 // clear those pointers that likely might have circular references to us
998 owner = 0; 1044 owner = 0;
1045 enemy = 0;
1046 attacked_by = 0;
999 1047
1000 /* Remove object from the active list */ 1048 /* Remove object from the active list */
1001 speed = 0; 1049 speed = 0;
1002 update_ob_speed (this); 1050 update_ob_speed (this);
1003 1051
1015sub_weight (object *op, signed long weight) 1063sub_weight (object *op, signed long weight)
1016{ 1064{
1017 while (op != NULL) 1065 while (op != NULL)
1018 { 1066 {
1019 if (op->type == CONTAINER) 1067 if (op->type == CONTAINER)
1020 {
1021 weight = (signed long) (weight * (100 - op->stats.Str) / 100); 1068 weight = (signed long) (weight * (100 - op->stats.Str) / 100);
1022 } 1069
1023 op->carrying -= weight; 1070 op->carrying -= weight;
1024 op = op->env; 1071 op = op->env;
1025 } 1072 }
1026} 1073}
1027 1074
1035 */ 1082 */
1036 1083
1037void 1084void
1038remove_ob (object *op) 1085remove_ob (object *op)
1039{ 1086{
1087 object *tmp, *last = 0;
1040 object * 1088 object *otmp;
1041 tmp, *
1042 last = NULL;
1043 object *
1044 otmp;
1045 1089
1046 tag_t 1090 tag_t tag;
1047 tag;
1048 int
1049 check_walk_off; 1091 int check_walk_off;
1050 mapstruct * 1092 mapstruct *m;
1051 m;
1052 1093
1053 sint16 1094 sint16 x, y;
1054 x,
1055 y;
1056 1095
1057 if (QUERY_FLAG (op, FLAG_REMOVED)) 1096 if (QUERY_FLAG (op, FLAG_REMOVED))
1058 return; 1097 return;
1059 1098
1060 SET_FLAG (op, FLAG_REMOVED); 1099 SET_FLAG (op, FLAG_REMOVED);
1223 * This function goes through all objects below and including top, and 1262 * This function goes through all objects below and including top, and
1224 * merges op to the first matching object. 1263 * merges op to the first matching object.
1225 * If top is NULL, it is calculated. 1264 * If top is NULL, it is calculated.
1226 * Returns pointer to object if it succeded in the merge, otherwise NULL 1265 * Returns pointer to object if it succeded in the merge, otherwise NULL
1227 */ 1266 */
1228
1229object * 1267object *
1230merge_ob (object *op, object *top) 1268merge_ob (object *op, object *top)
1231{ 1269{
1232 if (!op->nrof) 1270 if (!op->nrof)
1233 return 0; 1271 return 0;
1249 free_object (op); 1287 free_object (op);
1250 return top; 1288 return top;
1251 } 1289 }
1252 } 1290 }
1253 1291
1254 return NULL; 1292 return 0;
1255} 1293}
1256 1294
1257/* 1295/*
1258 * 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
1259 * job preparing multi-part monsters 1297 * job preparing multi-part monsters
1586 remove_ob (tmp); 1624 remove_ob (tmp);
1587 free_object (tmp); 1625 free_object (tmp);
1588 } 1626 }
1589 } 1627 }
1590 1628
1591 tmp1 = arch_to_object (find_archetype (arch_string)); 1629 tmp1 = arch_to_object (archetype::find (arch_string));
1592 1630
1593 tmp1->x = op->x; 1631 tmp1->x = op->x;
1594 tmp1->y = op->y; 1632 tmp1->y = op->y;
1595 insert_ob_in_map (tmp1, op->map, op, 0); 1633 insert_ob_in_map (tmp1, op->map, op, 0);
1596} 1634}
2654 2692
2655 if (tempfile == NULL) 2693 if (tempfile == NULL)
2656 { 2694 {
2657 LOG (llevError, "Error - Unable to access load object temp file\n"); 2695 LOG (llevError, "Error - Unable to access load object temp file\n");
2658 return NULL; 2696 return NULL;
2659 }; 2697 }
2698
2660 fprintf (tempfile, obstr); 2699 fprintf (tempfile, obstr);
2661 fclose (tempfile); 2700 fclose (tempfile);
2662 2701
2663 op = get_object (); 2702 op = get_object ();
2664 2703
2721 * The returned string is shared. 2760 * The returned string is shared.
2722 */ 2761 */
2723const char * 2762const char *
2724get_ob_key_value (const object *op, const char *const key) 2763get_ob_key_value (const object *op, const char *const key)
2725{ 2764{
2726 key_value * 2765 key_value *link;
2727 link; 2766 shstr_cmp canonical_key (key);
2728 const char *
2729 canonical_key;
2730 2767
2731 canonical_key = shstr::find (key);
2732
2733 if (canonical_key == NULL) 2768 if (!canonical_key)
2734 { 2769 {
2735 /* 1. There being a field named key on any object 2770 /* 1. There being a field named key on any object
2736 * implies there'd be a shared string to find. 2771 * implies there'd be a shared string to find.
2737 * 2. Since there isn't, no object has this field. 2772 * 2. Since there isn't, no object has this field.
2738 * 3. Therefore, *this* object doesn't have this field. 2773 * 3. Therefore, *this* object doesn't have this field.
2739 */ 2774 */
2740 return NULL; 2775 return 0;
2741 } 2776 }
2742 2777
2743 /* This is copied from get_ob_key_link() above - 2778 /* This is copied from get_ob_key_link() above -
2744 * only 4 lines, and saves the function call overhead. 2779 * only 4 lines, and saves the function call overhead.
2745 */ 2780 */
2746 for (link = op->key_values; link != NULL; link = link->next) 2781 for (link = op->key_values; link; link = link->next)
2747 {
2748 if (link->key == canonical_key) 2782 if (link->key == canonical_key)
2749 {
2750 return link->value; 2783 return link->value;
2751 } 2784
2752 }
2753 return NULL; 2785 return 0;
2754} 2786}
2755 2787
2756 2788
2757/* 2789/*
2758 * Updates the canonical_key in op to value. 2790 * Updates the canonical_key in op to value.
2844 shstr key_ (key); 2876 shstr key_ (key);
2845 2877
2846 return set_ob_key_value_s (op, key_, value, add_key); 2878 return set_ob_key_value_s (op, key_, value, add_key);
2847} 2879}
2848 2880
2881object::depth_iterator::depth_iterator (object *container)
2882: iterator_base (container)
2883{
2884 while (item->inv)
2885 item = item->inv;
2886}
2887
2849void 2888void
2850object::deep_iterator::next () 2889object::depth_iterator::next ()
2851{ 2890{
2852 if (item->inv)
2853 item = item->inv;
2854 else if (item->below) 2891 if (item->below)
2892 {
2855 item = item->below; 2893 item = item->below;
2894
2895 while (item->inv)
2896 item = item->inv;
2897 }
2856 else 2898 else
2857 item = item->env->below; 2899 item = item->env;
2858} 2900}
2901
2902// return a suitable string describing an objetc in enough detail to find it
2903const char *
2904object::debug_desc (char *info) const
2905{
2906 char info2[256 * 3];
2907 char *p = info;
2908
2909 p += snprintf (p, 256, "%d=\"%s%s%s\"",
2910 count,
2911 &name,
2912 title ? " " : "",
2913 title ? (const char *)title : "");
2914
2915 if (env)
2916 p += snprintf (p, 256, "(in %s)", env->debug_desc (info2));
2917
2918 if (map)
2919 p += snprintf (p, 256, "(on %s@%d+%d)", map->path, x, y);
2920
2921 return info;
2922}
2923
2924const char *
2925object::debug_desc () const
2926{
2927 static char info[256 * 3];
2928 return debug_desc (info);
2929}
2930

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines