/** * \brief Changes the name of an entity. * \param index Index of the entity on the map. * \param name The new name. An empty string means no name. * \return \c true in case of success, \c false if the name was already used. */ bool MapData::set_entity_name(const EntityIndex& index, const std::string& name) { EntityData& entity = get_entity(index); const std::string& old_name = entity.get_name(); if (name == old_name) { // Nothing to do. return true; } if (!name.empty()) { if (entity_exists(name)) { // This name is already used by another entity. return false; } } // Do the change. entity.set_name(name); if (!old_name.empty()) { named_entities.erase(old_name); } if (!name.empty()) { named_entities[name] = index; } return false; }
/** * \brief Returns the entity at the given layer and index. * * Non-const version. * * \param index Index of the entity to get on the map. * \return The entity data. * The object remains valid until entities are added or removed. */ EntityData& MapData::get_entity(const EntityIndex& index) { Debug::check_assertion(entity_exists(index), "Entity index out of range" ); return get_entities(index.layer)[index.order]; }
/** * \brief Adds an entity to the map at the specified index. * * If the new entity has a name, it should be unique on the map. * * \param entity The information of an entity. * \param index The index this entity should have on the map. * \return \c false in case of failure, that is, * if the name was already in use, if the entity type is illegal * or if the index was out of range. */ bool MapData::insert_entity(const EntityData& entity, const EntityIndex& index) { if (!EntityTypeInfo::can_be_stored_in_map_file(entity.get_type())) { // Illegal type of entity in a map file. return false; } const Layer layer = index.layer; int order = index.order; bool dynamic = entity.is_dynamic(); int min_order = dynamic ? get_num_tiles(layer) : 0; int max_order = dynamic ? get_num_entities(layer) : get_num_tiles(layer); if (order < min_order || order > max_order) { // Index out of range. return false; } if (entity.has_name()) { if (entity_exists(entity.get_name())) { // This name is already used by another entity. return false; } named_entities.emplace(entity.get_name(), index); } if (!dynamic) { ++this->entities[layer].num_tiles; } std::deque<EntityData>& entities = get_entities(layer); auto it = entities.begin() + order; entities.emplace(it, entity); // Indexes after this one get shifted. for (it = entities.begin() + order + 1; it != entities.end(); ++it ) { const EntityData& current_entity = *it; const std::string& name = current_entity.get_name(); if (!name.empty()) { EntityIndex& index = named_entities[name]; ++index.order; } } return true; }
entity_t entity_new(uint32_t type) { type = type & TYPE_MASK; entity_t entity; ue_lock.lock(); if (unused.size() > 0 && entity_retrieve_by_type(type, &entity)) { ue_lock.unlock(); } else { ue_lock.unlock(); ne_lock.lock(); entity = next_entity; entity_t start = next_entity - 1; while(entity_exists(entity) && start != next_entity) { next_entity = (next_entity + 1) & ENTITY_MASK; entity = next_entity | type; } ne_lock.unlock(); // Invalid entity if (start == next_entity) { entity = entity | ENTITY_MASK; } } // If it was a valid entity, add it to the claimed entities vector if ((entity & ENTITY_MASK) != ENTITY_MASK) { ce_lock.lock(); claimed.push_back(entity); ce_lock.unlock(); } return entity; }
/** * \brief Removes an entity from the map. * \param index Index of the entity on the map. * \return \c false in case of failure, that is, * if the index is out of range. */ bool MapData::remove_entity(const EntityIndex& index) { if (!entity_exists(index)) { return false; } Layer layer = index.layer; int order = index.order; const EntityData& entity = get_entity(index); bool dynamic = entity.is_dynamic(); if (entity.has_name()) { named_entities.erase(entity.get_name()); } if (!dynamic) { --this->entities[layer].num_tiles; } std::deque<EntityData>& entities = get_entities(layer); auto it = entities.begin() + order; entities.erase(it); // Indexes after this one get shifted. for (it = entities.begin() + order; it != entities.end(); ++it) { const EntityData& current_entity = *it; const std::string& name = current_entity.get_name(); if (!name.empty()) { EntityIndex& index = named_entities[name]; --index.order; } } return true; }