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.203 by root, Fri Apr 11 13:59:05 2008 UTC vs.
Revision 1.206 by root, Tue Apr 15 14:21:04 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] = { 45short freearr_x[SIZEOFFREE] = {
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 (UUID_SKIP, true); 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);
109 _exit (1); 112 _exit (1);
110 } 113 }
111 114
112 LOG (llevDebug, "read UUID: %s\n", UUID::cur.c_str ()); 115 LOG (llevDebug, "read UUID: %s\n", UUID::cur.c_str ());
113 116
114 write_uuid (UUID_SKIP, true); 117 write_uuid (UUID_GAP, true);
115 fclose (fp); 118 fclose (fp);
116} 119}
117 120
118UUID 121UUID
119UUID::gen () 122UUID::gen ()
120{ 123{
121 UUID uid; 124 UUID uid;
122 125
123 uid.seq = ++cur.seq; 126 uid.seq = ++cur.seq;
124 127
125 if (expect_false (!(cur.seq & (UUID_SKIP - 1)))) 128 if (expect_false (cur.seq >= seq_next_save))
129 {
130 seq_next_save = UUID::cur.seq + (UUID_GAP >> 1);
126 write_uuid (UUID_SKIP, false); 131 write_uuid (UUID_GAP, false);
132 }
133
127 134
128 return uid; 135 return uid;
129} 136}
130 137
131void 138void
133{ 140{
134 read_uuid (); 141 read_uuid ();
135} 142}
136 143
137/* 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. */
138static int 145static bool
139compare_ob_value_lists_one (const object *wants, const object *has) 146compare_ob_value_lists_one (const object *wants, const object *has)
140{ 147{
141 key_value *wants_field; 148 key_value *wants_field;
142 149
143 /* 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
151 key_value *has_field; 158 key_value *has_field;
152 159
153 /* Look for a field in has with the same key. */ 160 /* Look for a field in has with the same key. */
154 has_field = get_ob_key_link (has, wants_field->key); 161 has_field = get_ob_key_link (has, wants_field->key);
155 162
156 if (has_field == NULL) 163 if (!has_field)
157 {
158 /* No field with that name. */ 164 return 0; /* No field with that name. */
159 return FALSE;
160 }
161 165
162 /* Found the matching field. */ 166 /* Found the matching field. */
163 if (has_field->value != wants_field->value) 167 if (has_field->value != wants_field->value)
164 {
165 /* 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. */
166 return FALSE;
167 }
168 169
169 /* 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. */
170 } 171 }
171 172
172 /* 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. */
173 return TRUE; 174 return 1;
174} 175}
175 176
176/* Returns TRUE if ob1 has the same key_values as ob2. */ 177/* Returns TRUE if ob1 has the same key_values as ob2. */
177static int 178static bool
178compare_ob_value_lists (const object *ob1, const object *ob2) 179compare_ob_value_lists (const object *ob1, const object *ob2)
179{ 180{
180 /* 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,
181 * so we need to run the comparison *twice*. :( 182 * so we need to run the comparison *twice*. :(
182 */ 183 */
203 || ob1->speed != ob2->speed 204 || ob1->speed != ob2->speed
204 || ob1->value != ob2->value 205 || ob1->value != ob2->value
205 || ob1->name != ob2->name) 206 || ob1->name != ob2->name)
206 return 0; 207 return 0;
207 208
208 //TODO: this ain't working well, use nicer and correct overflow check 209 /* Do not merge objects if nrof would overflow. First part checks
209 /* 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
210 * 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
211 * used to store nrof). 212 * nrof values.
212 */ 213 */
213 if (ob1->nrof + ob2->nrof >= 1UL << 31) 214 if (~ob1->nrof < ob2->nrof || ob1->nrof + ob2->nrof > (1UL << 31))
214 return 0; 215 return 0;
215 216
216 /* If the objects have been identified, set the BEEN_APPLIED flag. 217 /* If the objects have been identified, set the BEEN_APPLIED flag.
217 * 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
218 * 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
219 * 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
220 * flags lose any meaning. 221 * flags lose any meaning.
221 */ 222 */
222 if (QUERY_FLAG (ob1, FLAG_IDENTIFIED)) 223 if (QUERY_FLAG (ob1, FLAG_IDENTIFIED))
250 || ob1->move_off != ob2->move_off 251 || ob1->move_off != ob2->move_off
251 || ob1->move_slow != ob2->move_slow 252 || ob1->move_slow != ob2->move_slow
252 || ob1->move_slow_penalty != ob2->move_slow_penalty) 253 || ob1->move_slow_penalty != ob2->move_slow_penalty)
253 return 0; 254 return 0;
254 255
255 /* This is really a spellbook check - really, we should 256 /* This is really a spellbook check - we should in general
256 * check all objects in the inventory. 257 * not merge objects with real inventories, as splitting them
258 * is hard.
257 */ 259 */
258 if (ob1->inv || ob2->inv) 260 if (ob1->inv || ob2->inv)
259 { 261 {
260 if (!(ob1->inv && ob2->inv)) 262 if (!(ob1->inv && ob2->inv))
261 return 0; /* inventories differ in length */ 263 return 0; /* inventories differ in length */
262 264
263 if (ob1->inv->below || ob2->inv->below) 265 if (ob1->inv->below || ob2->inv->below)
264 return 0; /* more than one object in inv */ 266 return 0; /* more than one object in inv */
265 267
266 if (!object::can_merge (ob1->inv, ob2->inv)) 268 if (!object::can_merge (ob1->inv, ob2->inv))
267 return 0; /* inventory objexts differ */ 269 return 0; /* inventory objects differ */
268 270
269 /* 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
270 * if it is valid. 272 * if it is valid.
271 */ 273 */
272 } 274 }
291 if (ob1->level != ob2->level) 293 if (ob1->level != ob2->level)
292 return 0; 294 return 0;
293 break; 295 break;
294 } 296 }
295 297
296 if (ob1->key_values != NULL || ob2->key_values != NULL) 298 if (ob1->key_values || ob2->key_values)
297 { 299 {
298 /* At least one of these has key_values. */ 300 /* At least one of these has key_values. */
299 if ((ob1->key_values == NULL) != (ob2->key_values == NULL)) 301 if ((!ob1->key_values) != (!ob2->key_values))
300 /* One has fields, but the other one doesn't. */ 302 /* One has fields, but the other one doesn't. */
301 return 0; 303 return 0;
302 else if (!compare_ob_value_lists (ob1, ob2)) 304 else if (!compare_ob_value_lists (ob1, ob2))
303 return 0; 305 return 0;
304 } 306 }
861 * if some form of movement is allowed, let objects 863 * if some form of movement is allowed, let objects
862 * drop on that space. 864 * drop on that space.
863 */ 865 */
864 if (!drop_to_ground 866 if (!drop_to_ground
865 || !map 867 || !map
866 || map->in_memory != MAP_IN_MEMORY 868 || map->in_memory != MAP_ACTIVE
867 || map->nodrop 869 || map->nodrop
868 || ms ().move_block == MOVE_ALL) 870 || ms ().move_block == MOVE_ALL)
869 { 871 {
870 while (inv) 872 while (inv)
871 { 873 {
933 freed_map->width = 3; 935 freed_map->width = 3;
934 freed_map->height = 3; 936 freed_map->height = 3;
935 freed_map->nodrop = 1; 937 freed_map->nodrop = 1;
936 938
937 freed_map->alloc (); 939 freed_map->alloc ();
938 freed_map->in_memory = MAP_IN_MEMORY; 940 freed_map->in_memory = MAP_ACTIVE;
939 } 941 }
940 942
941 map = freed_map; 943 map = freed_map;
942 x = 1; 944 x = 1;
943 y = 1; 945 y = 1;
1477} 1479}
1478 1480
1479object * 1481object *
1480object::insert_at (object *where, object *originator, int flags) 1482object::insert_at (object *where, object *originator, int flags)
1481{ 1483{
1484 if (where->env)
1485 return where->env->insert (this);
1486 else
1482 return where->map->insert (this, where->x, where->y, originator, flags); 1487 return where->map->insert (this, where->x, where->y, originator, flags);
1483} 1488}
1484 1489
1485/* 1490/*
1486 * 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
1487 * is returned contains nr objects, and the remaining parts contains 1492 * is returned contains nr objects, and the remaining parts contains
1507 orig_ob->destroy (1); 1512 orig_ob->destroy (1);
1508 else if (!is_removed) 1513 else if (!is_removed)
1509 { 1514 {
1510 if (orig_ob->env != NULL) 1515 if (orig_ob->env != NULL)
1511 sub_weight (orig_ob->env, orig_ob->weight * nr); 1516 sub_weight (orig_ob->env, orig_ob->weight * nr);
1512 if (orig_ob->env == NULL && orig_ob->map->in_memory != MAP_IN_MEMORY) 1517 if (orig_ob->env == NULL && orig_ob->map->in_memory != MAP_ACTIVE)
1513 { 1518 {
1514 strcpy (errmsg, "Tried to split object whose map is not in memory."); 1519 strcpy (errmsg, "Tried to split object whose map is not in memory.");
1515 LOG (llevDebug, "Error, Tried to split object whose map is not in memory.\n"); 1520 LOG (llevDebug, "Error, Tried to split object whose map is not in memory.\n");
1516 return NULL; 1521 return NULL;
1517 } 1522 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines