2012-02-08 04:36:54 -08:00
2011-10-03 11:41:19 -07:00
# pragma once
# ifndef _WIN32
2012-02-13 13:47:03 -08:00
# include "BlockID.h"
2011-10-03 11:41:19 -07:00
# else
2012-02-13 13:47:03 -08:00
enum ENUM_ITEM_ID ;
2011-10-03 11:41:19 -07:00
# endif
2011-12-23 15:58:54 -08:00
# define MAX_PLAYERS 65535
2011-12-26 12:57:12 -08:00
# include "cSimulatorManager.h"
2012-02-08 04:36:54 -08:00
# include "MersenneTwister.h"
2012-02-13 13:47:03 -08:00
# include "cChunkMap.h"
# include "WorldStorage.h"
# include "cChunkGenerator.h"
2012-03-01 07:18:59 -08:00
# include "Vector3i.h"
2012-03-05 08:41:57 -08:00
# include "ChunkSender.h"
2012-03-07 05:36:30 -08:00
# include "Defines.h"
2011-12-26 12:57:12 -08:00
2012-01-29 11:28:19 -08:00
2011-11-07 18:02:13 -08:00
class cPacket ;
2011-11-08 17:31:19 -08:00
class cRedstone ;
2011-12-28 13:00:35 -08:00
class cFireSimulator ;
2011-10-03 11:41:19 -07:00
class cWaterSimulator ;
2011-11-06 01:23:20 -08:00
class cLavaSimulator ;
2011-12-26 12:57:12 -08:00
class cSandSimulator ;
2012-03-01 07:18:59 -08:00
class cRedstoneSimulator ;
2011-10-03 11:41:19 -07:00
class cItem ;
class cPlayer ;
class cClientHandle ;
class cEntity ;
class cBlockEntity ;
2012-02-13 13:47:03 -08:00
class cWorldGenerator ; // The generator that actually generates the chunks for a single world
class cChunkGenerator ; // The thread responsible for generating chunks
typedef std : : list < cPlayer * > cPlayerList ;
2012-02-16 05:42:35 -08:00
typedef cItemCallback < cPlayer > cPlayerListCallback ;
2012-02-16 09:20:28 -08:00
typedef cItemCallback < cEntity > cEntityCallback ;
2012-02-13 13:47:03 -08:00
2011-12-26 12:57:12 -08:00
2011-10-03 11:41:19 -07:00
class cWorld //tolua_export
{ //tolua_export
public :
2011-11-08 17:31:19 -08:00
2012-03-10 14:27:24 -08:00
OBSOLETE static cWorld * GetWorld ( ) ; //tolua_export
2011-10-03 11:41:19 -07:00
// Return time in seconds
inline static float GetTime ( ) //tolua_export
{
return m_Time ;
}
2012-03-07 05:36:30 -08:00
long long GetWorldTime ( void ) const { return m_WorldTime ; } //tolua_export
2011-10-26 13:52:19 -07:00
2012-03-07 05:36:30 -08:00
eGameMode GetGameMode ( void ) const { return m_GameMode ; } //tolua_export
2011-10-26 13:52:19 -07:00
2011-10-03 11:41:19 -07:00
void SetWorldTime ( long long a_WorldTime ) { m_WorldTime = a_WorldTime ; } //tolua_export
2012-02-18 09:53:22 -08:00
int GetHeight ( int a_X , int a_Z ) ; //tolua_export
2011-10-03 11:41:19 -07:00
2011-11-07 18:02:13 -08:00
void Broadcast ( const cPacket & a_Packet , cClientHandle * a_Exclude = 0 ) ;
2012-02-28 00:10:51 -08:00
void BroadcastToChunk ( int a_ChunkX , int a_ChunkY , int a_ChunkZ , const cPacket & a_Packet , cClientHandle * a_Exclude = NULL ) ;
2012-02-16 05:42:35 -08:00
void BroadcastToChunkOfBlock ( int a_X , int a_Y , int a_Z , cPacket * a_Packet , cClientHandle * a_Exclude = NULL ) ;
2012-02-16 09:45:26 -08:00
void MarkChunkDirty ( int a_ChunkX , int a_ChunkY , int a_ChunkZ ) ;
void MarkChunkSaving ( int a_ChunkX , int a_ChunkY , int a_ChunkZ ) ;
void MarkChunkSaved ( int a_ChunkX , int a_ChunkY , int a_ChunkZ ) ;
void ChunkDataLoaded ( int a_ChunkX , int a_ChunkY , int a_ChunkZ , const char * a_BlockData , cEntityList & a_Entities , cBlockEntityList & a_BlockEntities ) ;
2012-02-18 09:53:22 -08:00
void ChunkDataGenerated ( int a_ChunkX , int a_ChunkY , int a_ChunkZ , const char * a_BlockData , cEntityList & a_Entities , cBlockEntityList & a_BlockEntities ) ;
2012-03-09 05:42:28 -08:00
bool GetChunkData ( int a_ChunkX , int a_ChunkY , int a_ChunkZ , cChunkDataCallback & a_Callback ) ;
2012-03-05 08:41:57 -08:00
/// Gets the chunk's blocks, only the block types
2012-02-18 11:18:16 -08:00
bool GetChunkBlocks ( int a_ChunkX , int a_ChunkY , int a_ChunkZ , char * a_Blocks ) ;
2012-03-05 08:41:57 -08:00
/// Gets the chunk's blockdata, the entire array
bool GetChunkBlockData ( int a_ChunkX , int a_ChunkY , int a_ChunkZ , char * a_BlockData ) ;
2012-02-16 09:45:26 -08:00
bool IsChunkValid ( int a_ChunkX , int a_ChunkY , int a_ChunkZ ) const ;
bool HasChunkAnyClients ( int a_ChunkX , int a_ChunkY , int a_ChunkZ ) const ;
2012-02-16 11:32:31 -08:00
void UnloadUnusedChunks ( void ) ;
2012-02-20 08:39:00 -08:00
void CollectPickupsByPlayer ( cPlayer * a_Player ) ;
2012-02-16 11:32:31 -08:00
2011-12-23 15:58:54 -08:00
// MOTD
2012-03-07 05:36:30 -08:00
const AString & GetDescription ( void ) const { return m_Description ; } // FIXME: This should not be in cWorld
2011-12-23 15:58:54 -08:00
// Max Players
2012-03-07 05:36:30 -08:00
unsigned int GetMaxPlayers ( void ) const { return m_MaxPlayers ; } //tolua_export
void SetMaxPlayers ( int iMax ) ; //tolua_export
2011-11-07 18:02:13 -08:00
2011-10-03 11:41:19 -07:00
void AddPlayer ( cPlayer * a_Player ) ;
void RemovePlayer ( cPlayer * a_Player ) ;
2012-02-14 11:14:23 -08:00
2011-10-03 11:41:19 -07:00
typedef struct lua_State lua_State ;
2012-02-16 14:28:19 -08:00
bool ForEachPlayer ( cPlayerListCallback & a_Callback ) ; // Calls the callback for each player in the list
2012-02-14 11:14:23 -08:00
// >> EXPORTED IN MANUALBINDINGS <<
2011-10-03 11:41:19 -07:00
unsigned int GetNumPlayers ( ) ; //tolua_export
2012-02-13 13:47:03 -08:00
2012-02-14 13:09:14 -08:00
// TODO: This interface is dangerous - rewrite to DoWithPlayer(playername, action)
2012-03-07 05:36:30 -08:00
cPlayer * GetPlayer ( const char * a_PlayerName ) ; //tolua_export
2012-02-13 13:47:03 -08:00
2012-02-14 13:09:14 -08:00
// TODO: This interface is dangerous - rewrite to DoWithClosestPlayer(pos, sight, action)
2012-02-13 13:47:03 -08:00
cPlayer * FindClosestPlayer ( const Vector3f & a_Pos , float a_SightLimit ) ;
void SendPlayerList ( cPlayer * a_DestPlayer ) ; // Sends playerlist to the player
2011-10-03 11:41:19 -07:00
void AddEntity ( cEntity * a_Entity ) ;
2012-02-20 08:39:00 -08:00
/// Add an entity to the chunk specified; broadcasts the a_SpawnPacket to all clients of that chunk
void AddEntityToChunk ( cEntity * a_Entity , int a_ChunkX , int a_ChunkY , int a_ChunkZ , cPacket * a_SpawnPacket ) ;
/// Removes the entity from the chunk specified
void RemoveEntityFromChunk ( cEntity * a_Entity , int a_ChunkX , int a_ChunkY , int a_ChunkZ ) ;
/// Moves the entity from its current chunk to the new chunk specified
void MoveEntityToChunk ( cEntity * a_Entity , int a_ChunkX , int a_ChunkY , int a_ChunkZ ) ;
/// Compares clients of two chunks, calls the callback accordingly
void CompareChunkClients ( int a_ChunkX1 , int a_ChunkY1 , int a_ChunkZ1 , int a_ChunkX2 , int a_ChunkY2 , int a_ChunkZ2 , cClientDiffCallback & a_Callback ) ;
2012-02-21 07:18:02 -08:00
/// Adds client to a chunk, if not already present; returns true if added, false if present
bool AddChunkClient ( int a_ChunkX , int a_ChunkY , int a_ChunkZ , cClientHandle * a_Client ) ;
2012-02-21 08:27:30 -08:00
/// Removes client from the chunk specified
void RemoveChunkClient ( int a_ChunkX , int a_ChunkY , int a_ChunkZ , cClientHandle * a_Client ) ;
2012-02-21 07:18:02 -08:00
/// Removes the client from all chunks specified
void RemoveClientFromChunks ( cClientHandle * a_Client , const cChunkCoordsList & a_Chunks ) ;
2012-03-06 06:52:44 -08:00
/// Sends the chunk to the client specified, if the chunk is valid. If not valid, the request is ignored (ChunkSender will send that chunk when it becomes valid)
void SendChunkTo ( int a_ChunkX , int a_ChunkY , int a_ChunkZ , cClientHandle * a_Client ) ;
/// Removes client from ChunkSender's queue of chunks to be sent
void RemoveClientFromChunkSender ( cClientHandle * a_Client ) ;
2012-02-21 08:27:30 -08:00
/// Touches the chunk, causing it to be loaded or generated
void TouchChunk ( int a_ChunkX , int a_ChunkY , int a_ChunkZ ) ;
2012-02-28 02:45:53 -08:00
/// Loads the chunk, if not already loaded. Doesn't generate. Returns true if chunk valid (even if already loaded before)
bool LoadChunk ( int a_ChunkX , int a_ChunkY , int a_ChunkZ ) ;
/// Loads the chunks specified. Doesn't report failure, other than chunks being !IsValid()
void LoadChunks ( const cChunkCoordsList & a_Chunks ) ;
2012-02-28 04:11:14 -08:00
/// Marks the chunk as failed-to-load:
void ChunkLoadFailed ( int a_ChunkX , int a_ChunkY , int a_ChunkZ ) ;
2012-03-07 05:36:30 -08:00
void UpdateSign ( int a_X , int a_Y , int a_Z , const AString & a_Line1 , const AString & a_Line2 , const AString & a_Line3 , const AString & a_Line4 ) ; //tolua_export
2011-10-03 11:41:19 -07:00
2012-02-28 02:45:53 -08:00
/// Marks (a_Stay == true) or unmarks (a_Stay == false) chunks as non-unloadable. To be used only by cChunkStay!
void ChunksStay ( const cChunkCoordsList & a_Chunks , bool a_Stay = true ) ;
2012-02-26 08:15:09 -08:00
2012-02-16 09:20:28 -08:00
// TODO: Export to Lua
bool DoWithEntity ( int a_UniqueID , cEntityCallback & a_Callback ) ;
2011-10-03 11:41:19 -07:00
2012-03-07 05:36:30 -08:00
void SetBlock ( int a_X , int a_Y , int a_Z , char a_BlockType , char a_BlockMeta ) ; //tolua_export
void FastSetBlock ( int a_X , int a_Y , int a_Z , char a_BlockType , char a_BlockMeta ) ; //tolua_export
char GetBlock ( int a_X , int a_Y , int a_Z ) ; //tolua_export
char GetBlock ( const Vector3i & a_Pos ) { return GetBlock ( a_Pos . x , a_Pos . y , a_Pos . z ) ; } //tolua_export
char GetBlockMeta ( int a_X , int a_Y , int a_Z ) ; //tolua_export
char GetBlockMeta ( const Vector3i & a_Pos ) { return GetBlockMeta ( a_Pos . x , a_Pos . y , a_Pos . z ) ; } //tolua_export
void SetBlockMeta ( int a_X , int a_Y , int a_Z , char a_MetaData ) ; //tolua_export
2012-03-01 07:18:59 -08:00
void SetBlockMeta ( const Vector3i & a_Pos , char a_MetaData ) { SetBlockMeta ( a_Pos . x , a_Pos . y , a_Pos . z , a_MetaData ) ; } //tolua_export
2012-03-07 05:36:30 -08:00
bool DigBlock ( int a_X , int a_Y , int a_Z , cItem & a_PickupItem ) ; //tolua_export
void SendBlockTo ( int a_X , int a_Y , int a_Z , cPlayer * a_Player ) ; //tolua_export
2011-10-03 11:41:19 -07:00
2012-03-07 05:36:30 -08:00
const double & GetSpawnX ( ) { return m_SpawnX ; } //tolua_export
const double & GetSpawnY ( ) ; //tolua_export
const double & GetSpawnZ ( ) { return m_SpawnZ ; } //tolua_export
2011-10-03 11:41:19 -07:00
2011-12-26 12:57:12 -08:00
inline cSimulatorManager * GetSimulatorManager ( ) { return m_SimulatorManager ; }
inline cWaterSimulator * GetWaterSimulator ( ) { return m_WaterSimulator ; }
inline cLavaSimulator * GetLavaSimulator ( ) { return m_LavaSimulator ; }
2011-12-22 13:36:24 -08:00
2012-02-16 05:42:35 -08:00
// TODO: This interface is dangerous! Export as a set of specific action functions for Lua: GetChestItem, GetFurnaceItem, SetFurnaceItem, SetSignLines etc.
2012-02-21 08:27:30 -08:00
// _X 2012_02_21: This function always returns NULL
OBSOLETE cBlockEntity * GetBlockEntity ( int a_X , int a_Y , int a_Z ) ; //tolua_export
2012-02-15 06:22:44 -08:00
/// a_Player is using block entity at [x, y, z], handle that:
void UseBlockEntity ( cPlayer * a_Player , int a_X , int a_Y , int a_Z ) { m_ChunkMap - > UseBlockEntity ( a_Player , a_X , a_Y , a_Z ) ; }
2011-10-03 11:41:19 -07:00
2012-03-07 05:36:30 -08:00
void GrowTree ( int a_X , int a_Y , int a_Z ) ; //tolua_export
2011-10-03 11:41:19 -07:00
2012-02-13 13:47:03 -08:00
unsigned int GetWorldSeed ( void ) const { return m_WorldSeed ; } //tolua_export
2012-03-07 05:36:30 -08:00
const AString & GetName ( void ) const { return m_WorldName ; } //tolua_export
2012-03-12 12:39:41 -07:00
const AString & GetIniFileName ( void ) const { return m_IniFileName ; }
2011-10-03 11:41:19 -07:00
inline static void AbsoluteToRelative ( int & a_X , int & a_Y , int & a_Z , int & a_ChunkX , int & a_ChunkY , int & a_ChunkZ )
{
2012-03-03 12:55:16 -08:00
// TODO: Use floor() instead of weird if statements
// Also fix Y
a_ChunkX = a_X / cChunk : : c_ChunkWidth ;
if ( a_X < 0 & & a_X % cChunk : : c_ChunkWidth ! = 0 ) a_ChunkX - - ;
2011-10-03 11:41:19 -07:00
a_ChunkY = 0 ;
2012-03-03 12:55:16 -08:00
a_ChunkZ = a_Z / cChunk : : c_ChunkWidth ;
if ( a_Z < 0 & & a_Z % cChunk : : c_ChunkWidth ! = 0 ) a_ChunkZ - - ;
2011-10-03 11:41:19 -07:00
2012-03-03 12:55:16 -08:00
a_X = a_X - a_ChunkX * cChunk : : c_ChunkWidth ;
a_Y = a_Y - a_ChunkY * cChunk : : c_ChunkHeight ;
a_Z = a_Z - a_ChunkZ * cChunk : : c_ChunkWidth ;
2011-10-03 11:41:19 -07:00
}
2012-02-13 13:47:03 -08:00
2011-10-03 11:41:19 -07:00
inline static void BlockToChunk ( int a_X , int a_Y , int a_Z , int & a_ChunkX , int & a_ChunkY , int & a_ChunkZ )
{
2012-03-03 12:55:16 -08:00
// TODO: Use floor() instead of weird if statements
// Also fix Y
2011-10-03 11:41:19 -07:00
( void ) a_Y ; // not unused anymore
2012-03-03 12:55:16 -08:00
a_ChunkX = a_X / cChunk : : c_ChunkWidth ;
if ( a_X < 0 & & a_X % cChunk : : c_ChunkWidth ! = 0 ) a_ChunkX - - ;
2011-10-03 11:41:19 -07:00
a_ChunkY = 0 ;
2012-03-03 12:55:16 -08:00
a_ChunkZ = a_Z / cChunk : : c_ChunkWidth ;
if ( a_Z < 0 & & a_Z % cChunk : : c_ChunkWidth ! = 0 ) a_ChunkZ - - ;
2011-10-03 11:41:19 -07:00
}
2012-03-07 05:36:30 -08:00
void SaveAllChunks ( ) ; //tolua_export
2012-02-13 13:47:03 -08:00
int GetNumChunks ( ) const ; //tolua_export
2011-10-03 11:41:19 -07:00
void Tick ( float a_Dt ) ;
2012-02-18 09:53:22 -08:00
void ReSpreadLighting ( int a_ChunkX , int a_ChunkY , int a_ChunkZ ) ;
void RemoveSpread ( int a_ChunkX , int a_ChunkY , int a_ChunkZ ) ;
2011-10-03 11:41:19 -07:00
void InitializeSpawn ( ) ;
2011-11-08 17:31:19 -08:00
2012-03-07 05:36:30 -08:00
void CastThunderbolt ( int a_X , int a_Y , int a_Z ) ; //tolua_export
void SetWeather ( eWeather a_Weather ) ; //tolua_export
eWeather GetWeather ( ) { return m_Weather ; } ; //tolua_export
2011-11-09 15:24:51 -08:00
2012-02-13 13:47:03 -08:00
cChunkGenerator & GetGenerator ( void ) { return m_Generator ; }
cWorldStorage & GetStorage ( void ) { return m_Storage ; }
2012-02-18 09:53:22 -08:00
cChunkMap * GetChunkMap ( void ) { return m_ChunkMap ; }
2012-02-08 04:36:54 -08:00
2011-10-03 11:41:19 -07:00
private :
2012-02-08 04:36:54 -08:00
2011-10-03 11:41:19 -07:00
friend class cRoot ;
2012-02-08 04:36:54 -08:00
// This random generator is to be used only in the Tick() method, and thus only in the World-Tick-thread (MTRand is not exactly thread-safe)
MTRand m_TickRand ;
2011-10-03 11:41:19 -07:00
double m_SpawnX ;
double m_SpawnY ;
double m_SpawnZ ;
float m_LastUnload ;
float m_LastSave ;
static float m_Time ; // Time in seconds
long long m_WorldTime ; // Time in seconds*20, this is sent to clients (is wrapped)
2011-11-06 01:23:20 -08:00
unsigned long long CurrentTick ;
2012-03-07 05:36:30 -08:00
eGameMode m_GameMode ;
2011-10-03 11:41:19 -07:00
float m_WorldTimeFraction ; // When this > 1.f m_WorldTime is incremented by 20
2012-02-13 13:47:03 -08:00
// The cRedstone class simulates redstone and needs access to m_RSList
friend class cRedstone ;
std : : vector < int > m_RSList ;
2012-03-01 07:18:59 -08:00
cSimulatorManager * m_SimulatorManager ;
cSandSimulator * m_SandSimulator ;
cWaterSimulator * m_WaterSimulator ;
cLavaSimulator * m_LavaSimulator ;
cFireSimulator * m_FireSimulator ;
cRedstoneSimulator * m_RedstoneSimulator ;
2011-12-26 12:57:12 -08:00
2012-02-13 13:47:03 -08:00
cCriticalSection m_CSClients ;
cCriticalSection m_CSEntities ;
cCriticalSection m_CSPlayers ;
2011-12-26 15:23:05 -08:00
2012-02-13 13:47:03 -08:00
cWorldStorage m_Storage ;
AString m_Description ;
2011-12-23 15:58:54 -08:00
unsigned int m_MaxPlayers ;
2011-10-03 11:41:19 -07:00
2012-02-13 13:47:03 -08:00
cChunkMap * m_ChunkMap ;
2011-10-03 11:41:19 -07:00
bool m_bAnimals ;
float m_SpawnMonsterTime ;
float m_SpawnMonsterRate ;
unsigned int m_WorldSeed ;
2012-02-13 13:47:03 -08:00
2012-03-07 05:36:30 -08:00
eWeather m_Weather ;
2012-02-08 04:36:54 -08:00
2012-02-13 13:47:03 -08:00
cEntityList m_RemoveEntityQueue ;
cEntityList m_AllEntities ;
cClientHandleList m_Clients ;
cPlayerList m_Players ;
2012-02-08 04:36:54 -08:00
2012-02-13 13:47:03 -08:00
cCriticalSection m_CSLighting ;
2012-02-18 09:53:22 -08:00
cChunkCoordsList m_SpreadQueue ;
2012-02-08 04:36:54 -08:00
2012-02-13 13:47:03 -08:00
cCriticalSection m_CSFastSetBlock ;
2012-02-18 12:10:57 -08:00
sSetBlockList m_FastSetBlockQueue ;
2012-02-13 13:47:03 -08:00
cChunkGenerator m_Generator ;
2012-03-05 08:41:57 -08:00
cChunkSender m_ChunkSender ;
2012-02-13 13:47:03 -08:00
AString m_WorldName ;
2012-03-12 12:39:41 -07:00
AString m_IniFileName ;
2012-02-13 13:47:03 -08:00
cWorld ( const AString & a_WorldName ) ;
~ cWorld ( ) ;
void TickWeather ( float a_Dt ) ; // Handles weather each tick
void TickSpawnMobs ( float a_Dt ) ; // Handles mob spawning each tick
2012-02-18 09:53:22 -08:00
void TickLighting ( void ) ; // Handles lighting re-spreading
2012-02-13 13:47:03 -08:00
void RemoveEntity ( cEntity * a_Entity ) ;
2011-10-03 11:41:19 -07:00
} ; //tolua_export
2012-02-08 04:36:54 -08:00