Index: game/GridStates.cpp =================================================================== --- game/GridStates.cpp (revision 4014) +++ game/GridStates.cpp (working copy) @@ -30,11 +30,19 @@ void ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 &x, const uint32 &y, const uint32 &t_diff) const { - if( grid.ActiveObjectsInGrid() == 0 && !ObjectAccessor::Instance().PlayersNearGrid(x, y, m.GetId(), m.GetInstanceId()) ) + // Only check grid activity every (grid_expiry/10) ms, because it's really useless to do it every cycle + info.i_timer.Update(t_diff); + if (info.i_timer.Passed()) { - ObjectGridStoper stoper(grid); - stoper.StopN(); - grid.SetGridState(GRID_STATE_IDLE); + if( grid.ActiveObjectsInGrid() == 0 && !ObjectAccessor::Instance().PlayersNearGrid(x, y, m.GetId(), m.GetInstanceId()) ) + { + ObjectGridStoper stoper(grid); + stoper.StopN(); + grid.SetGridState(GRID_STATE_IDLE); + } else + { + m.ResetGridExpiry(info, 0.1f); + } } } Index: game/Map.cpp =================================================================== --- game/Map.cpp (revision 4014) +++ game/Map.cpp (working copy) @@ -73,27 +73,34 @@ return true; } -GridMap * Map::LoadMAP(uint32 mapid, uint32 instanceid, int x,int y) +void Map::LoadMAP(uint32 mapid, uint32 instanceid, int x,int y) { //check map file existance (but not output error) - if(!Map::ExistMAP(mapid,x,y,false)) - return NULL; + if (!Map::ExistMAP(mapid,x,y,false)) + return; if (instanceid != 0) { - // load from base map - if (GridMaps[x][y]) GridMaps[x][y]=NULL; + if (GridMaps[x][y]) + return; - if (!MapManager::Instance().GetBaseMap(mapid)->GridMaps[x][y]) - { - // load grids for base map - MapManager::Instance().GetBaseMap(mapid)->GridMaps[x][y] = Map::LoadMAP(mapid, 0, x, y); - } + Map* baseMap = MapManager::Instance().GetBaseMap(mapid); - return(MapManager::Instance().GetBaseMap(mapid)->GridMaps[x][y]); + // load gridmap for base map + if (!baseMap->GridMaps[x][y]) + baseMap->EnsureGridCreated(GridPair(63-x,63-y)); + + if (!baseMap->GridMaps[x][y]) + return; + + ((MapInstanced*)(baseMap))->AddGridMapReference(GridPair(x,y)); + baseMap->SetUnloadFlag(GridPair(63-x,63-y), false); + GridMaps[x][y] = baseMap->GridMaps[x][y]; + return; } - if(GridMaps[x][y]) //map already load, delete it before reloading + //map already load, delete it before reloading (Is it neccessary? Do we really need the abilty the reload maps during runtime?) + if(GridMaps[x][y]) { sLog.outDetail("Unloading already loaded map %u before reloading.",mapid); delete (GridMaps[x][y]); @@ -117,11 +124,12 @@ if(!buf) //unexpected error { fclose(pf); - return NULL; + return; } fread(buf,1,sizeof(GridMap),pf); fclose(pf); - return buf; + + GridMaps[x][y] = buf; } void Map::InitStateMachine() @@ -142,7 +150,6 @@ Map::Map(uint32 id, time_t expiry, uint32 ainstanceId) : i_id(id), i_gridExpiry(expiry), i_mapEntry (sMapStore.LookupEntry(id)), i_resetTime(0), i_InstanceId(ainstanceId) { - // char tmp[32]; for(unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx) { i_gridMask[idx] = 0; @@ -152,8 +159,6 @@ //z code GridMaps[idx][j] =NULL; - //z code - i_grids[idx][j] = NULL; i_info[idx][j] = NULL; } @@ -342,14 +347,15 @@ i_grids[p.x_coord][p.y_coord] = new NGridType(p.x_coord*MAX_NUMBER_OF_GRIDS + p.y_coord); i_info[p.x_coord][p.y_coord] = new GridInfo(i_gridExpiry,sWorld.getConfig(CONFIG_GRID_UNLOAD)); i_gridMask[p.x_coord] |= mask; + + i_grids[p.x_coord][p.y_coord]->SetGridState(GRID_STATE_IDLE); + //z coord - int gx=63-p.x_coord; int gy=63-p.y_coord; if(!GridMaps[gx][gy]) - GridMaps[gx][gy]=Map::LoadMAP(i_id,i_InstanceId,gx,gy); - + Map::LoadMAP(i_id,i_InstanceId,gx,gy); } } @@ -384,6 +390,7 @@ // Add resurrectable corpses to world object list in grid ObjectAccessor::Instance().AddCorpsesToGrid(GridPair(cell.GridX(),cell.GridY()),(*grid)(cell.CellX(), cell.CellY()), this); + ResetGridExpiry(*i_info[cell.GridX()][cell.GridY()], 0.1f); grid->SetGridState(GRID_STATE_ACTIVE); if( add_player && player != NULL ) @@ -966,8 +973,11 @@ UpdateObjectsVisibilityFor(player,new_cell,new_val); PlayerRelocationNotify(player,new_cell,new_val); - if( !same_cell ) + if( !same_cell && i_grids[new_cell.GridX()][new_cell.GridY()]->GetGridState()!=GRID_STATE_ACTIVE ) + { + ResetGridExpiry(*i_info[new_cell.GridX()][new_cell.GridY()], 0.1f); i_grids[new_cell.GridX()][new_cell.GridY()]->SetGridState(GRID_STATE_ACTIVE); + } } void @@ -1167,15 +1177,16 @@ int gx=63-x; int gy=63-y; - // delete grid map, but don't delete grid map if it is from parent map - // FIXME: we must delete also in case single loaded instance or none loaded instances - if(GridMaps[gx][gy]) + // delete grid map, but don't delete if it is from parent map (and thus only reference) + if (GridMaps[gx][gy]) { - if (i_InstanceId == 0) delete (GridMaps[gx][gy]); - GridMaps[gx][gy]=NULL; + if (i_InstanceId == 0) + delete (GridMaps[gx][gy]); + else + ((MapInstanced*)(MapManager::Instance().GetBaseMap(i_id)))->RemoveGridMapReference(GridPair(gx, gy)); + GridMaps[gx][gy] = NULL; } - //z coordinate DEBUG_LOG("Unloading grid[%u,%u] for map %u finished", x,y, i_id); return true; } @@ -1189,7 +1200,6 @@ { if( i_gridMask[i] & mask ) UnloadGrid(i, j); - mask <<= 1; } } @@ -1221,8 +1231,7 @@ ly=MAP_RESOLUTION*(32 -y/SIZE_OF_GRIDS - gy); //DEBUG_LOG("my %d %d si %d %d",gx,gy,p.x_coord,p.y_coord); - if(!GridMaps[gx][gy]) //this map is not loaded - GridMaps[gx][gy]=Map::LoadMAP(i_id,i_InstanceId,gx,gy); + EnsureGridCreated(GridPair(63-gx,63-gy)); // ensure GridMap is loaded if(GridMaps[gx][gy]) return GridMaps[gx][gy]->Z[(int)(lx)][(int)(ly)]; @@ -1256,8 +1265,7 @@ ly=16*(32 -y/SIZE_OF_GRIDS - gy); //DEBUG_LOG("my %d %d si %d %d",gx,gy,p.x_coord,p.y_coord); - if(!GridMaps[gx][gy]) //this map is not loaded - GridMaps[gx][gy]=Map::LoadMAP(i_id,i_InstanceId,gx,gy); + EnsureGridCreated(GridPair(63-gx,63-gy)); // ensure GridMap is loaded if(GridMaps[gx][gy]) return GridMaps[gx][gy]->area_flag[(int)(lx)][(int)(ly)]; @@ -1291,8 +1299,7 @@ lx=16*(32 -x/SIZE_OF_GRIDS - gx); ly=16*(32 -y/SIZE_OF_GRIDS - gy); - if(!GridMaps[gx][gy]) //this map is not loaded - GridMaps[gx][gy]=Map::LoadMAP(i_id,i_InstanceId,gx,gy); + EnsureGridCreated(GridPair(63-gx,63-gy)); // ensure GridMap is loaded if(GridMaps[gx][gy]) return GridMaps[gx][gy]->terrain_type[(int)(lx)][(int)(ly)]; @@ -1326,8 +1333,7 @@ lx=128*(32 -x/SIZE_OF_GRIDS - gx); ly=128*(32 -y/SIZE_OF_GRIDS - gy); - if(!GridMaps[gx][gy]) //this map is not loaded - GridMaps[gx][gy]=Map::LoadMAP(i_id,i_InstanceId,gx,gy); + EnsureGridCreated(GridPair(63-gx,63-gy)); // ensure GridMap is loaded if(GridMaps[gx][gy]) return GridMaps[gx][gy]->liquid_level[(int)(lx)][(int)(ly)]; Index: game/Map.h =================================================================== --- game/Map.h (revision 4014) +++ game/Map.h (working copy) @@ -92,6 +92,7 @@ public: Map(uint32 id, time_t, uint32 aInstanceId); + virtual ~Map() {}; // Important! Else memleak at MapInstanced class destruction void Add(Player *); bool AddInstanced(Player *); @@ -148,16 +149,16 @@ bool UnloadGrid(const uint32 &x, const uint32 &y); virtual void UnloadAll(); - void ResetGridExpiry(GridInfo &info) const + void ResetGridExpiry(GridInfo &info, float factor = 1) const { - info.i_timer.Reset(i_gridExpiry); + info.i_timer.Reset((time_t)((float)i_gridExpiry*factor)); } time_t GetGridExpiry(void) const { return i_gridExpiry; } uint32 GetId(void) const { return i_id; } static bool ExistMAP(uint32 mapid, int x, int y, bool output = true); - GridMap * LoadMAP(uint32 mapid, uint32 instanceid, int x, int y); + void LoadMAP(uint32 mapid, uint32 instanceid, int x, int y); static void InitStateMachine(); static void DeleteStateMachine(); Index: game/MapInstanced.cpp =================================================================== --- game/MapInstanced.cpp (revision 4014) +++ game/MapInstanced.cpp (working copy) @@ -25,10 +25,16 @@ { // initialize instanced maps list InstancedMaps.clear(); + // fill with zero + memset(&GridMapReference, 0, MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_GRIDS*sizeof(uint16)); } void MapInstanced::Update(const uint32& t) { + // take care of loaded GridMaps (when unused, unload it!) + Map::Update(t); + + // update the instanced maps HM_NAMESPACE::hash_map< uint32, Map* >::iterator i = InstancedMaps.begin(); while (i != InstancedMaps.end()) @@ -83,10 +89,16 @@ void MapInstanced::UnloadAll() { + // Unload instanced maps for (HM_NAMESPACE::hash_map< uint32, Map* >::iterator i = InstancedMaps.begin(); i != InstancedMaps.end(); i++) { i->second->UnloadAll(); + delete i->second; } + InstancedMaps.clear(); + + // Unload own grids (just dummy(placeholder) grids, neccesary to unload GridMaps!) + Map::UnloadAll(); } Map* MapInstanced::GetInstance(const WorldObject* obj) Index: game/MapInstanced.h =================================================================== --- game/MapInstanced.h (revision 4014) +++ game/MapInstanced.h (working copy) @@ -26,6 +26,7 @@ public: MapInstanced(uint32 id, time_t, uint32 aInstanceId); + ~MapInstanced() {} // Important! Else memleak at class destruction virtual void Update(const uint32&); virtual void MoveAllCreaturesInMoveList(); @@ -35,6 +36,13 @@ Map* GetInstance(const WorldObject* obj); bool IsValidInstance(uint32 InstanceId); + void AddGridMapReference(const GridPair &p) { GridMapReference[p.x_coord][p.y_coord]++; } + void RemoveGridMapReference(const GridPair &p) + { + GridMapReference[p.x_coord][p.y_coord]--; + if (!GridMapReference[p.x_coord][p.y_coord]) { SetUnloadFlag(GridPair(63-p.x_coord,63-p.y_coord), true); } + } + private: void CreateInstance(uint32 InstanceId, Map* &map); @@ -47,6 +55,8 @@ return(i == InstancedMaps.end() ? NULL : i->second); } + + uint16 GridMapReference[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; }; #endif