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.202 by root, Thu Apr 10 15:35:15 2008 UTC vs.
Revision 1.205 by root, Sun Apr 13 01:34:08 2008 UTC

34#include <loader.h> 34#include <loader.h>
35 35
36#include <bitset> 36#include <bitset>
37 37
38UUID UUID::cur; 38UUID UUID::cur;
39static uint64_t seq_next_save;
39static const uint64 UUID_SKIP = 1<<19; 40static const uint64 UUID_GAP = 1<<19;
40 41
41objectvec objects; 42objectvec objects;
42activevec actives; 43activevec actives;
43 44
44short 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, 45short freearr_x[SIZEOFFREE] = {
46 0,
47 0, 1, 1, 1, 0, -1, -1, -1,
48 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2, -2, -2, -2, -1,
45 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3, -3, -3, -3, -3, -2, -1 49 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3, -3, -3, -3, -3, -2, -1
46}; 50};
47short freearr_y[SIZEOFFREE] = { 0, -1, -1, 0, 1, 1, 1, 0, -1, -2, -2, -2, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2, 51short freearr_y[SIZEOFFREE] = {
52 0,
53 -1, -1, 0, 1, 1, 1, 0, -1,
54 -2, -2, -2, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2,
48 -3, -3, -3, -3, -2, -1, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3 55 -3, -3, -3, -3, -2, -1, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3
49}; 56};
50int maxfree[SIZEOFFREE] = { 0, 9, 10, 13, 14, 17, 18, 21, 22, 25, 26, 27, 30, 31, 32, 33, 36, 37, 39, 39, 42, 43, 44, 45, 57int maxfree[SIZEOFFREE] = {
58 0,
59 9, 10, 13, 14, 17, 18, 21, 22,
60 25, 26, 27, 30, 31, 32, 33, 36, 37, 39, 39, 42, 43, 44, 45, 48,
51 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49 61 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49
52}; 62};
53int freedir[SIZEOFFREE] = { 63int freedir[SIZEOFFREE] = {
54 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, 64 0,
65 1, 2, 3, 4, 5, 6, 7, 8,
66 1, 2, 2, 2, 3, 4, 4, 4, 5, 6, 6, 6, 7, 8, 8, 8,
55 1, 2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 7, 8, 8, 8, 8, 8 67 1, 2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 7, 8, 8, 8, 8, 8
56}; 68};
57 69
58static void 70static void
59write_uuid (void) 71write_uuid (uval64 skip, bool sync)
60{ 72{
61 char filename1[MAX_BUF], filename2[MAX_BUF]; 73 CALL_BEGIN (2);
62 74 CALL_ARG_SV (newSVval64 (skip));
63 sprintf (filename1, "%s/uuid", settings.localdir); 75 CALL_ARG_SV (boolSV (sync));
64 sprintf (filename2, "%s/uuid~", settings.localdir); 76 CALL_CALL ("cf::write_uuid", G_DISCARD);
65 77 CALL_END;
66 FILE *fp;
67
68 if (!(fp = fopen (filename2, "w")))
69 {
70 LOG (llevError, "ERROR: cannot open %s for writing, unable to write UUID!\n", filename2);
71 return;
72 }
73
74 fprintf (fp, "<1,%llx>\n", (unsigned long long)UUID::cur.seq + UUID_SKIP * 2);
75 fclose (fp);
76 rename (filename2, filename1);
77} 78}
78 79
79static void 80static void
80read_uuid (void) 81read_uuid (void)
81{ 82{
82 char filename[MAX_BUF]; 83 char filename[MAX_BUF];
83 84
84 sprintf (filename, "%s/uuid", settings.localdir); 85 sprintf (filename, "%s/uuid", settings.localdir);
85 86
87 seq_next_save = 0;
88
86 FILE *fp; 89 FILE *fp;
87 90
88 if (!(fp = fopen (filename, "r"))) 91 if (!(fp = fopen (filename, "r")))
89 { 92 {
90 if (errno == ENOENT) 93 if (errno == ENOENT)
91 { 94 {
92 LOG (llevInfo, "RESET uid to 1\n"); 95 LOG (llevInfo, "RESET uid to 1\n");
93 UUID::cur.seq = 0; 96 UUID::cur.seq = 0;
94 write_uuid (); 97 write_uuid (UUID_GAP, true);
95 return; 98 return;
96 } 99 }
97 100
98 LOG (llevError, "FATAL: cannot open %s for reading!\n", filename); 101 LOG (llevError, "FATAL: cannot open %s for reading!\n", filename);
99 _exit (1); 102 _exit (1);
100 } 103 }
101 104
102 int version; 105 UUID::BUF buf;
103 unsigned long long uid; 106 buf[0] = 0;
104 if (2 != fscanf (fp, "<%d,%llx>\n", &version, &uid) || version != 1) 107 fgets (buf, sizeof (buf), fp);
108
109 if (!UUID::cur.parse (buf))
105 { 110 {
106 LOG (llevError, "FATAL: error reading uid from %s!\n", filename); 111 LOG (llevError, "FATAL: error reading uid from %s (%s)!\n", filename, buf);
107 _exit (1); 112 _exit (1);
108 } 113 }
109 114
110 UUID::cur.seq = uid; 115 LOG (llevDebug, "read UUID: %s\n", UUID::cur.c_str ());
111 write_uuid (); 116
112 LOG (llevDebug, "read UID: %" PRId64 "\n", uid); 117 write_uuid (UUID_GAP, true);
113 fclose (fp); 118 fclose (fp);
114} 119}
115 120
116UUID 121UUID
117UUID::gen () 122UUID::gen ()
118{ 123{
119 UUID uid; 124 UUID uid;
120 125
121 uid.seq = ++cur.seq; 126 uid.seq = ++cur.seq;
122 127
123 if (!(cur.seq & (UUID_SKIP - 1))) 128 if (expect_false (cur.seq >= seq_next_save))
124 write_uuid (); 129 {
130 seq_next_save = UUID::cur.seq + (UUID_GAP >> 1);
131 write_uuid (UUID_GAP, false);
132 }
133
125 134
126 return uid; 135 return uid;
127} 136}
128 137
129void 138void
131{ 140{
132 read_uuid (); 141 read_uuid ();
133} 142}
134 143
135/* Returns TRUE if every key_values in wants has a partner with the same value in has. */ 144/* Returns TRUE if every key_values in wants has a partner with the same value in has. */
136static int 145static bool
137compare_ob_value_lists_one (const object *wants, const object *has) 146compare_ob_value_lists_one (const object *wants, const object *has)
138{ 147{
139 key_value *wants_field; 148 key_value *wants_field;
140 149
141 /* n-squared behaviour (see get_ob_key_link()), but I'm hoping both 150 /* n-squared behaviour (see get_ob_key_link()), but I'm hoping both
149 key_value *has_field; 158 key_value *has_field;
150 159
151 /* Look for a field in has with the same key. */ 160 /* Look for a field in has with the same key. */
152 has_field = get_ob_key_link (has, wants_field->key); 161 has_field = get_ob_key_link (has, wants_field->key);
153 162
154 if (has_field == NULL) 163 if (!has_field)
155 {
156 /* No field with that name. */ 164 return 0; /* No field with that name. */
157 return FALSE;
158 }
159 165
160 /* Found the matching field. */ 166 /* Found the matching field. */
161 if (has_field->value != wants_field->value) 167 if (has_field->value != wants_field->value)
162 {
163 /* Values don't match, so this half of the comparison is false. */ 168 return 0; /* Values don't match, so this half of the comparison is false. */
164 return FALSE;
165 }
166 169
167 /* If we get here, we found a match. Now for the next field in wants. */ 170 /* If we get here, we found a match. Now for the next field in wants. */
168 } 171 }
169 172
170 /* If we get here, every field in wants has a matching field in has. */ 173 /* If we get here, every field in wants has a matching field in has. */
171 return TRUE; 174 return 1;
172} 175}
173 176
174/* Returns TRUE if ob1 has the same key_values as ob2. */ 177/* Returns TRUE if ob1 has the same key_values as ob2. */
175static int 178static bool
176compare_ob_value_lists (const object *ob1, const object *ob2) 179compare_ob_value_lists (const object *ob1, const object *ob2)
177{ 180{
178 /* However, there may be fields in has which aren't partnered in wants, 181 /* However, there may be fields in has which aren't partnered in wants,
179 * so we need to run the comparison *twice*. :( 182 * so we need to run the comparison *twice*. :(
180 */ 183 */
201 || ob1->speed != ob2->speed 204 || ob1->speed != ob2->speed
202 || ob1->value != ob2->value 205 || ob1->value != ob2->value
203 || ob1->name != ob2->name) 206 || ob1->name != ob2->name)
204 return 0; 207 return 0;
205 208
206 //TODO: this ain't working well, use nicer and correct overflow check 209 /* Do not merge objects if nrof would overflow. First part checks
207 /* Do not merge objects if nrof would overflow. We use 1UL<<31 since that 210 * for unsigned overflow (2c), second part checks wether the result
208 * value could not be stored in a sint32 (which unfortunately sometimes is 211 * would fit into a 32 bit signed int, which is often used to hold
209 * used to store nrof). 212 * nrof values.
210 */ 213 */
211 if (ob1->nrof + ob2->nrof >= 1UL << 31) 214 if (~ob1->nrof < ob2->nrof || ob1->nrof + ob2->nrof > (1UL << 31))
212 return 0; 215 return 0;
213 216
214 /* If the objects have been identified, set the BEEN_APPLIED flag. 217 /* If the objects have been identified, set the BEEN_APPLIED flag.
215 * This is to the comparison of the flags below will be OK. We 218 * This is to the comparison of the flags below will be OK. We
216 * just can't ignore the been applied or identified flags, as they 219 * just can't ignore the been applied or identified flags, as they
217 * are not equal - just if it has been identified, the been_applied 220 * are not equal - just if it has been identified, the been_applied
218 * flags lose any meaning. 221 * flags lose any meaning.
219 */ 222 */
220 if (QUERY_FLAG (ob1, FLAG_IDENTIFIED)) 223 if (QUERY_FLAG (ob1, FLAG_IDENTIFIED))
248 || ob1->move_off != ob2->move_off 251 || ob1->move_off != ob2->move_off
249 || ob1->move_slow != ob2->move_slow 252 || ob1->move_slow != ob2->move_slow
250 || ob1->move_slow_penalty != ob2->move_slow_penalty) 253 || ob1->move_slow_penalty != ob2->move_slow_penalty)
251 return 0; 254 return 0;
252 255
253 /* This is really a spellbook check - really, we should 256 /* This is really a spellbook check - we should in general
254 * check all objects in the inventory. 257 * not merge objects with real inventories, as splitting them
258 * is hard.
255 */ 259 */
256 if (ob1->inv || ob2->inv) 260 if (ob1->inv || ob2->inv)
257 { 261 {
258 if (!(ob1->inv && ob2->inv)) 262 if (!(ob1->inv && ob2->inv))
259 return 0; /* inventories differ in length */ 263 return 0; /* inventories differ in length */
260 264
261 if (ob1->inv->below || ob2->inv->below) 265 if (ob1->inv->below || ob2->inv->below)
262 return 0; /* more than one object in inv */ 266 return 0; /* more than one object in inv */
263 267
264 if (!object::can_merge (ob1->inv, ob2->inv)) 268 if (!object::can_merge (ob1->inv, ob2->inv))
265 return 0; /* inventory objexts differ */ 269 return 0; /* inventory objects differ */
266 270
267 /* inventory ok - still need to check rest of this object to see 271 /* inventory ok - still need to check rest of this object to see
268 * if it is valid. 272 * if it is valid.
269 */ 273 */
270 } 274 }
289 if (ob1->level != ob2->level) 293 if (ob1->level != ob2->level)
290 return 0; 294 return 0;
291 break; 295 break;
292 } 296 }
293 297
294 if (ob1->key_values != NULL || ob2->key_values != NULL) 298 if (ob1->key_values || ob2->key_values)
295 { 299 {
296 /* At least one of these has key_values. */ 300 /* At least one of these has key_values. */
297 if ((ob1->key_values == NULL) != (ob2->key_values == NULL)) 301 if ((!ob1->key_values) != (!ob2->key_values))
298 /* One has fields, but the other one doesn't. */ 302 /* One has fields, but the other one doesn't. */
299 return 0; 303 return 0;
300 else if (!compare_ob_value_lists (ob1, ob2)) 304 else if (!compare_ob_value_lists (ob1, ob2))
301 return 0; 305 return 0;
302 } 306 }
1475} 1479}
1476 1480
1477object * 1481object *
1478object::insert_at (object *where, object *originator, int flags) 1482object::insert_at (object *where, object *originator, int flags)
1479{ 1483{
1484 if (where->env)
1485 return where->env->insert (this);
1486 else
1480 return where->map->insert (this, where->x, where->y, originator, flags); 1487 return where->map->insert (this, where->x, where->y, originator, flags);
1481} 1488}
1482 1489
1483/* 1490/*
1484 * get_split_ob(ob,nr) splits up ob into two parts. The part which 1491 * get_split_ob(ob,nr) splits up ob into two parts. The part which
1485 * is returned contains nr objects, and the remaining parts contains 1492 * is returned contains nr objects, and the remaining parts contains
2607{ 2614{
2608 char flagdesc[512]; 2615 char flagdesc[512];
2609 char info2[256 * 4]; 2616 char info2[256 * 4];
2610 char *p = info; 2617 char *p = info;
2611 2618
2612 p += snprintf (p, 512, "{cnt:%d,uuid:<1.%" PRIx64 ">,name:\"%s\"%s%s,flags:[%s],type:%d}", 2619 p += snprintf (p, 512, "{cnt:%d,uuid:%s,name:\"%s\"%s%s,flags:[%s],type:%d}",
2613 count, uuid.seq, 2620 count,
2621 uuid.c_str (),
2614 &name, 2622 &name,
2615 title ? "\",title:\"" : "", 2623 title ? "\",title:\"" : "",
2616 title ? (const char *)title : "", 2624 title ? (const char *)title : "",
2617 flag_desc (flagdesc, 512), type); 2625 flag_desc (flagdesc, 512), type);
2618 2626

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines