/*
* Ascent MMORPG Server
* Copyright (C) 2005-2007 Ascent Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#ifndef _TERRAINMGR_H
#define _TERRAINMGR_H
/* Use memory mapping for map files for faster access (currently only available under windows */
#ifdef WIN32
//#define USE_MEMORY_MAPPING_FOR_MAPS
#endif
typedef struct
{
uint16 AreaID[2][2];
uint8 LiquidType[2][2];
float LiquidLevel[2][2];
float Z[32][32];
}CellTerrainInformation;
#define FL2UINT (uint32)
#define TERRAIN_HEADER_SIZE 1048576 // size of [512][512] array.
#define MAP_RESOLUTION 256
/* @class TerrainMgr
TerrainMgr maintains the MapCellInfo information for accessing water levels,
water types, Z levels, area id's, and walkable graph information.
TerrainMgr can dynamically allocate and un-allocate cell information for main
continents as their information is *quite* large and not needed at all times
to be loaded. Unloading this in idle times is a nice way to save memory.
However, on instanced maps, we would want to keep the cell's information
loaded at all times as it is a lot smaller and we can have multiple instances
wanting to access this information at once.
*/
class TerrainMgr
{
public:
/* Initializes the terrain interface, allocates all required arrays, and sets
all variables.
Parameter 1: The path to the packed map files.
Parameter 2: The map that we'll be retrieving information from.
Parameter 3: Controls whether the map will unload information when it's not
in use.
No return value.
*/
TerrainMgr(string MapPath, uint32 MapId, bool Instanced);
/* Cleans up all arrays, and unloads any pending cell information.
No parameters.
No return value.
*/
~TerrainMgr();
/* If we're a non-instanced map, we'll unload the cell information as it's
not needed.
Parameter 1: The x co-ordinate of the cell that's gone idle.
Parameter 2: The y co-ordinate of the cell that's gone idle.
No return value.
*/
void CellGoneIdle(uint32 x, uint32 y);
/* Loads the cell information if it has not already been loaded.
Parameter 1: The x co-ordinate of the cell that's gone active.
Parameter 2: The y co-ordinate of the cell that's gone active.
No return value.
*/
void CellGoneActive(uint32 x, uint32 y);
/* Information retrieval functions
These functions all take the same input values, an x and y global co-ordinate.
They will all return 0 if the cell information is not loaded or does not exist,
apart from the water function which will return '-999999.0'.
*/
float GetLandHeight(float x, float y);
float GetWaterHeight(float x, float y);
uint8 GetWaterType(float x, float y);
uint8 GetWalkableState(float x, float y);
uint16 GetAreaID(float x, float y);
private:
/// MapPath contains the location of all mapfiles.
string mapPath;
/// Map ID
uint32 mapId;
/// Are we an instance?
bool Instance;
/// We don't want to be reading from a file from more than one thread at once
Mutex mutex;
#ifndef USE_MEMORY_MAPPING_FOR_MAPS
/// Our main file descriptor for accessing the binary terrain file.
FILE * FileDescriptor;
/// This holds the offsets of the cell information for each cell.
uint32 CellOffsets[_sizeX][_sizeY];
#else
/// Mapped file handle
HANDLE hMappedFile;
HANDLE hMap;
uint32 mFileSize;
/// This holds the offsets of the cell information for each cell.
uint32 CellOffsets[_sizeX][_sizeY];
#endif
/// Our storage array. This contains pointers to all allocated CellInfo's.
CellTerrainInformation *** CellInformation;
public:
/* Initializes the file descriptor and readys it for data retreival.
No parameters taken.
Returns true if the index was read successfully, false if not.
*/
bool LoadTerrainHeader();
protected:
/* Retrieves the cell data for the specified co-ordinates from the file and sets it in
the CellInformation array.
Parameter 1: x co-ordinate of the cell information to load.
Parameter 2: y co-ordinate of the cell information to load.
Returns true if the cell information exists and was loaded, false if not.
*/
bool LoadCellInformation(uint32 x, uint32 y);
/* Unloads the cell data at the specified co-ordinates and frees the memory.
Parameter 1: x co-ordinate of the cell information to free.
Parameter 2: y co-ordinate of the cell information to free.
Returns true if the free was successful, otherwise false.
*/
bool UnloadCellInformation(uint32 x, uint32 y);
/* Gets the offset for the specified cell from the cached offset index.
Parameter 1: cell x co-ordinate.
Parameter 2: cell y co-ordinate.
Returns the offset in bytes of that cell's information, or 0 if it doesn't exist.
*/
inline uint32 GetCellInformationOffset(uint32 x, uint32 y)
{
return CellOffsets[x][y];
}
/* Gets a cell information pointer so that another function can access its data.
Parameter 1: cell x co-ordinate.
Parameter 2: cell y co-ordinate.
Returns the memory address of the information for that cell.
*/
inline CellTerrainInformation* GetCellInformation(uint32 x, uint32 y)
{
return CellInformation[x][y];
}
/* Converts a global x co-ordinate into a cell x co-ordinate.
Parameter 1: global x co-ordinate.
Returns the cell x co-ordinate.
*/
inline uint32 ConvertGlobalXCoordinate(float x)
{
return FL2UINT((_maxX-x)/_cellSize);
}
/* Converts a global y co-ordinate into a cell y co-ordinate.
Parameter 1: global y co-ordinate.
Returns the cell y co-ordinate.
*/
inline uint32 ConvertGlobalYCoordinate(float y)
{
return FL2UINT((_maxY-y)/_cellSize);
}
/* Converts a global x co-ordinate into a INTERNAL cell x co-ordinate.
Parameter 1: global x co-ordinate.
Parameter 2: the cell x co-ordinate.
Returns the internal x co-ordinate.
*/
inline float ConvertInternalXCoordinate(float x, uint32 cellx)
{
float X = (_maxX - x);
X -= (cellx * _cellSize);
return X;
}
/* Converts a global y co-ordinate into a INTERNAL cell y co-ordinate.
Parameter 1: global y co-ordinate.
Parameter 2: the cell y co-ordinate.
Returns the internal y co-ordinate.
*/
inline float ConvertInternalYCoordinate(float y, uint32 celly)
{
float Y = (_maxY - y);
Y -= (celly * _cellSize);
return Y;
}
/* Checks whether a cell information is loaded or not.
*/
inline bool CellInformationLoaded(uint32 x, uint32 y)
{
if(CellInformation[x][y] != 0)
return true;
else
return false;
}
/* Converts the internal co-ordinate to an index in the
2 dimension areaid, or liquid type arrays.
*/
inline uint32 ConvertTo2dArray(float c)
{
return FL2UINT(c*(16/CellsPerTile/_cellSize));
}
/* Checks that the co-ordinates are within range.
*/
inline bool AreCoordinatesValid(float x, float y)
{
if(x > _maxX || x < _minX)
return false;
if(y > _maxY || y < _minY)
return false;
return true;
}
};
#endif