void cSectorMaps::add( cUObject* object ) { // Very powerful statement. It completely // annihilates the need to check for // nullpointers in our object-map if ( !object ) return; if ( isItemSerial( object->serial() ) ) { P_ITEM pItem = dynamic_cast<P_ITEM>( object ); if ( pItem ) { Coord_cl pos = pItem->pos(); std::map<unsigned char, cSectorMap*>::const_iterator it = itemmaps.find( pos.map ); if ( it == itemmaps.end() ) throw QString( "Couldn't find a map with the id %1." ).arg( pos.map ); it->second->addItem( ( cUObject * ) pItem ); Timing::instance()->addDecayItem( pItem ); } } else if ( isCharSerial( object->serial() ) ) { // This is a safety check to make sure that // stabled pets don't appear on our sectormap P_NPC npc = dynamic_cast<P_NPC>( object ); if ( npc && npc->stablemasterSerial() != INVALID_SERIAL ) { return; } // The same check for players P_PLAYER player = dynamic_cast<P_PLAYER>( object ); if ( player && !player->socket() && !player->logoutTime() ) { return; } P_CHAR pChar = dynamic_cast<P_CHAR>( object ); if ( pChar ) { Coord_cl pos = pChar->pos(); std::map<unsigned char, cSectorMap*>::const_iterator it = charmaps.find( pos.map ); if ( it == charmaps.end() ) throw QString( "Couldn't find a map with the id %1." ).arg( pos.map ); it->second->addItem( ( cUObject * ) pChar ); } } }
cSectorIterator* cSectorMaps::findObjects( MapType type, cSectorMap* sector, uint x1, uint y1, uint x2, uint y2 ) { // First step: count how many items we are going to hold unsigned int count = 0; unsigned int xBlock, yBlock; if ( x1 > x2 ) { std::swap( x1, x2 ); std::swap( y1, y2 ); } for ( xBlock = x1 / SECTOR_SIZE; xBlock <= x2 / SECTOR_SIZE; xBlock++ ) for ( yBlock = y1 / SECTOR_SIZE; yBlock <= y2 / SECTOR_SIZE; yBlock++ ) count += sector->countItems( ( xBlock * sector->gridHeight() ) + yBlock ); // Second step: actually "compile" our list of items cUObject** items = ( cUObject** ) malloc( count * sizeof( cUObject* ) ); unsigned int offset = 0; for ( xBlock = x1 / SECTOR_SIZE; xBlock <= x2 / SECTOR_SIZE; xBlock++ ) for ( yBlock = y1 / SECTOR_SIZE; yBlock <= y2 / SECTOR_SIZE; yBlock++ ) { // We *do* know that we allocated more memory than we need, but the effect is minimal! unsigned int block = ( xBlock * sector->gridHeight() ) + yBlock; if ( block >= sector->gridWidth() * sector->gridHeight() ) continue; if ( sector->grid[block] ) { for ( unsigned int i = 0; i < sector->grid[block]->count; ++i ) { cUObject* object = sector->grid[block]->data[i]; if ( object->pos().x >= x1 && object->pos().y >= y1 && object->pos().x <= x2 && object->pos().y <= y2 ) { // This sucks but we don't have much choice if (type == MT_CHARS) { P_PLAYER player = dynamic_cast<P_PLAYER>(object); // Exclude logged out players. if (!player || player->socket() || player->logoutTime()) { items[offset++] = object; } } else if (type == MT_MULTIS) { P_ITEM item = dynamic_cast<P_ITEM>(object); if (item && item->isMulti()) { items[offset++] = object; } } else { items[offset++] = object; } } } } } /* NOTE: Offset is our new count here. The count we measured previously was just there to measure the amount of memory we had to allocate for the list. */ switch ( type ) { case MT_ITEMS: case MT_MULTIS: return new cItemSectorIterator( offset, items ); case MT_CHARS: case MT_CHARSANDOFFLINE: return new cCharSectorIterator( offset, items ); default: return new cSectorIterator( offset, items ); }; }