--- deliantra/server/common/object.C 2006/09/10 16:00:23 1.24 +++ deliantra/server/common/object.C 2006/09/11 01:16:20 1.25 @@ -1,7 +1,7 @@ /* * static char *rcsid_object_c = - * "$Id: object.C,v 1.24 2006/09/10 16:00:23 root Exp $"; + * "$Id: object.C,v 1.25 2006/09/11 01:16:20 root Exp $"; */ /* @@ -509,7 +509,6 @@ op->ownercount = owner->count; owner->refcount++; - } /* Set the owner to clone's current owner and set the skill and experience @@ -537,8 +536,8 @@ else return; } - set_owner (op, owner); + set_owner (op, owner); } /* Zero the key_values on op, decrementing the shared-string @@ -564,6 +563,8 @@ free_key_values (this); + clear_owner (this); + name = 0; name_pl = 0; title = 0; @@ -914,17 +915,19 @@ update_object (op->more, action); } -static -std::vector < object *> - mortals; +static unordered_vector mortals; +static std::vector freed; void object::free_mortals () { - for (std::vector < object *>::iterator i = mortals.begin (); i != mortals.end (); ++i) - delete * - i; - - mortals.clear (); + for (unordered_vector::iterator i = mortals.begin (); i != mortals.end (); ) + if (!(*i)->refcount) + { + freed.push_back (*i); + mortals.erase (i); + } + else + ++i; } object::object () @@ -960,17 +963,34 @@ /* Remove this object from the list of used objects */ if (prev) - prev->next = next; + { + prev->next = next; + prev = 0; + } + if (next) - next->prev = prev; + { + next->prev = prev; + next = 0; + } + if (this == objects) objects = next; } object *object::create () { - object * + object *op; + + if (freed.empty ()) op = new object; + else + { + // highly annoying, but the only way to get it stable right now + op = freed.back (); freed.pop_back (); + op->~object (); + new ((void *)op) object; + } op->link (); return op; @@ -1064,6 +1084,8 @@ } } + clear_owner (this); + /* Remove object from the active list */ speed = 0; update_ob_speed (this); @@ -1377,25 +1399,22 @@ object * insert_ob_in_map (object *op, mapstruct *m, object *originator, int flag) { - object * - tmp, * - top, * - floor = NULL; - sint16 - x, - y; + object *tmp, *top, *floor = NULL; + sint16 x, y; if (QUERY_FLAG (op, FLAG_FREED)) { LOG (llevError, "Trying to insert freed object!\n"); return NULL; } + if (m == NULL) { dump_object (op); LOG (llevError, "Trying to insert in null-map!\n%s\n", errmsg); return op; } + if (out_of_map (m, op->x, op->y)) { dump_object (op); @@ -1409,12 +1428,14 @@ #endif return op; } + if (!QUERY_FLAG (op, FLAG_REMOVED)) { dump_object (op); LOG (llevError, "Trying to insert (map) inserted object.\n%s\n", errmsg); return op; } + if (op->more != NULL) { /* The part may be on a different map. */ @@ -1446,6 +1467,7 @@ return NULL; } } + CLEAR_FLAG (op, FLAG_REMOVED); /* Ideally, the caller figures this out. However, it complicates a lot @@ -1459,18 +1481,17 @@ /* this has to be done after we translate the coordinates. */ if (op->nrof && !(flag & INS_NO_MERGE)) - { - for (tmp = GET_MAP_OB (op->map, x, y); tmp != NULL; tmp = tmp->above) - if (CAN_MERGE (op, tmp)) - { - op->nrof += tmp->nrof; - remove_ob (tmp); - free_object (tmp); - } - } + for (tmp = GET_MAP_OB (op->map, x, y); tmp != NULL; tmp = tmp->above) + if (CAN_MERGE (op, tmp)) + { + op->nrof += tmp->nrof; + remove_ob (tmp); + free_object (tmp); + } CLEAR_FLAG (op, FLAG_APPLIED); /* hack for fixing F_APPLIED in items of dead people */ CLEAR_FLAG (op, FLAG_INV_LOCKED); + if (!QUERY_FLAG (op, FLAG_ALIVE)) CLEAR_FLAG (op, FLAG_NO_STEAL); @@ -1481,12 +1502,15 @@ LOG (llevError, "insert_ob_in_map called with INS_BELOW_ORIGINATOR when originator not on same space!\n"); abort (); } + op->above = originator; op->below = originator->below; + if (op->below) op->below->above = op; else SET_MAP_OB (op->map, op->x, op->y, op); + /* since *below* originator, no need to update top */ originator->below = op; } @@ -1495,8 +1519,7 @@ /* If there are other objects, then */ if ((!(flag & INS_MAP_LOAD)) && ((top = GET_MAP_OB (op->map, op->x, op->y)) != NULL)) { - object * - last = NULL; + object *last = NULL; /* * If there are multiple objects on this space, we do some trickier handling. @@ -1553,8 +1576,10 @@ top = last->below; } } /* If objects on this space */ + if (flag & INS_MAP_LOAD) top = GET_MAP_TOP (op->map, op->x, op->y); + if (flag & INS_ABOVE_FLOOR_ONLY) top = floor; @@ -1565,19 +1590,24 @@ if (!top) { op->above = GET_MAP_OB (op->map, op->x, op->y); + if (op->above) op->above->below = op; + op->below = NULL; SET_MAP_OB (op->map, op->x, op->y, op); } else { /* get inserted into the stack above top */ op->above = top->above; + if (op->above) op->above->below = op; + op->below = top; top->above = op; } + if (op->above == NULL) SET_MAP_TOP (op->map, op->x, op->y, op); } /* else not INS_BELOW_ORIGINATOR */ @@ -1590,10 +1620,8 @@ */ if (!(flag & INS_MAP_LOAD)) for (tmp = floor ? floor : GET_MAP_OB (op->map, op->x, op->y); tmp != NULL; tmp = tmp->above) - { - if (tmp->type == PLAYER) - tmp->contr->socket.update_look = 1; - } + if (tmp->type == PLAYER) + tmp->contr->socket.update_look = 1; /* If this object glows, it may affect lighting conditions that are * visible to others on this map. But update_all_los is really @@ -1622,7 +1650,6 @@ */ /* if this is not the head or flag has been passed, don't check walk on status */ - if (!(flag & INS_NO_WALK_ON) && !op->head) { if (check_move_on (op, originator)) @@ -1635,6 +1662,7 @@ if (check_move_on (tmp, originator)) return NULL; } + return op; } @@ -1645,10 +1673,8 @@ void replace_insert_ob_in_map (const char *arch_string, object *op) { - object * - tmp; - object * - tmp1; + object *tmp; + object *tmp1; /* first search for itself and remove any old instances */ @@ -1663,7 +1689,6 @@ tmp1 = arch_to_object (find_archetype (arch_string)); - tmp1->x = op->x; tmp1->y = op->y; insert_ob_in_map (tmp1, op->map, op, 0);