From 32880153ab76830311d8a1db3a157cd5ac6e5d9c Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Wed, 8 Feb 2012 12:36:54 +0000 Subject: MTRand class is not created in each tick, therefore much improving tick-thread time (now uses ~5 % CPU instead of one full core) git-svn-id: http://mc-server.googlecode.com/svn/trunk@245 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/Bindings.cpp | 6 +-- source/Bindings.h | 2 +- source/cChunk.cpp | 13 +++-- source/cChunk.h | 14 +++++- source/cChunkMap.cpp | 4 +- source/cChunkMap.h | 19 +++++++- source/cClientHandle.cpp | 19 ++++---- source/cRoot.cpp | 2 +- source/cWorld.cpp | 124 +++++++++++++++++++++++++++++++---------------- source/cWorld.h | 24 +++++++-- 10 files changed, 156 insertions(+), 71 deletions(-) diff --git a/source/Bindings.cpp b/source/Bindings.cpp index 14a25dc35..4b0bb9f46 100644 --- a/source/Bindings.cpp +++ b/source/Bindings.cpp @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 02/02/12 15:03:55. +** Generated automatically by tolua++-1.0.92 on 02/08/12 12:55:58. */ #ifndef __cplusplus @@ -15986,7 +15986,7 @@ static int tolua_set_cPacket_Login_m_Username(lua_State* tolua_S) if (!tolua_iscppstring(tolua_S,2,0,&tolua_err)) tolua_error(tolua_S,"#vinvalid type in variable assignment.",&tolua_err); #endif - self->m_Username = ((std::string) tolua_tocppstring(tolua_S,2,0)) + self->m_Username = ((AString) tolua_tocppstring(tolua_S,2,0)) ; return 0; } @@ -16046,7 +16046,7 @@ static int tolua_set_cPacket_Login_m_LevelType(lua_State* tolua_S) if (!tolua_iscppstring(tolua_S,2,0,&tolua_err)) tolua_error(tolua_S,"#vinvalid type in variable assignment.",&tolua_err); #endif - self->m_LevelType = ((std::string) tolua_tocppstring(tolua_S,2,0)) + self->m_LevelType = ((AString) tolua_tocppstring(tolua_S,2,0)) ; return 0; } diff --git a/source/Bindings.h b/source/Bindings.h index 3d3dc6f68..941263827 100644 --- a/source/Bindings.h +++ b/source/Bindings.h @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 02/02/12 15:03:55. +** Generated automatically by tolua++-1.0.92 on 02/08/12 12:55:58. */ /* Exported function */ diff --git a/source/cChunk.cpp b/source/cChunk.cpp index edd39a378..6bf5172ae 100644 --- a/source/cChunk.cpp +++ b/source/cChunk.cpp @@ -190,7 +190,7 @@ void cChunk::Initialize() -void cChunk::Tick(float a_Dt) +void cChunk::Tick(float a_Dt, MTRand & a_TickRandom) { if (m_bCalculateLighting) { @@ -356,11 +356,10 @@ void cChunk::Tick(float a_Dt) }; } - MTRand r1; // Tick dem blocks - int RandomX = r1.randInt(); - int RandomY = r1.randInt(); - int RandomZ = r1.randInt(); + int RandomX = a_TickRandom.randInt(); + int RandomY = a_TickRandom.randInt(); + int RandomZ = a_TickRandom.randInt(); for(int i = 0; i < 50; i++) { @@ -426,6 +425,10 @@ void cChunk::Tick(float a_Dt) } } + + + + char cChunk::GetHeight( int a_X, int a_Z ) { if( a_X >= 0 && a_X < 16 && a_Z >= 0 && a_Z < 16 ) diff --git a/source/cChunk.h b/source/cChunk.h index bd9882659..cd1122922 100644 --- a/source/cChunk.h +++ b/source/cChunk.h @@ -1,3 +1,4 @@ + #pragma once #define C_CHUNK_USE_INLINE 1 @@ -14,14 +15,23 @@ namespace Json class Value; }; + + + + class cWorld; -class cCriticalSection; class cFurnaceEntity; class cPacket; class cBlockEntity; class cEntity; class cClientHandle; class cServer; +class MTRand; + + + + + class cChunk { public: @@ -30,7 +40,7 @@ public: void Initialize(); - void Tick(float a_Dt); + void Tick(float a_Dt, MTRand & a_TickRandom); int GetPosX() { return m_PosX; } int GetPosY() { return m_PosY; } diff --git a/source/cChunkMap.cpp b/source/cChunkMap.cpp index a5721026f..424b26b5f 100644 --- a/source/cChunkMap.cpp +++ b/source/cChunkMap.cpp @@ -349,7 +349,7 @@ cChunk* cChunkMap::GetChunk( int a_X, int a_Y, int a_Z ) -void cChunkMap::Tick( float a_Dt ) +void cChunkMap::Tick( float a_Dt, MTRand & a_TickRandom ) { for( int lay = 0; lay < m_NumLayers; ++lay ) { @@ -358,7 +358,7 @@ void cChunkMap::Tick( float a_Dt ) cChunk* Chunk = m_Layers[lay].m_Chunks[i].m_LiveChunk; if ( Chunk != NULL) { - Chunk->Tick( a_Dt ); + Chunk->Tick( a_Dt, a_TickRandom ); } } } // for lay - m_Layers[] diff --git a/source/cChunkMap.h b/source/cChunkMap.h index f2d1f4468..9cab98221 100644 --- a/source/cChunkMap.h +++ b/source/cChunkMap.h @@ -1,8 +1,19 @@ + #pragma once + + + + class cWorld; class cEntity; class cChunk; +class MTRand; + + + + + class cChunkMap { public: @@ -15,7 +26,7 @@ public: cChunk* GetChunk( int a_X, int a_Y, int a_Z ); void RemoveChunk( cChunk* a_Chunk ); - void Tick( float a_Dt ); + void Tick( float a_Dt, MTRand & a_TickRand ); void UnloadUnusedChunks(); bool RemoveEntityFromChunk( cEntity & a_Entity, cChunk* a_CalledFrom = 0 ); @@ -24,7 +35,9 @@ public: cWorld* GetWorld() { return m_World; } int GetNumChunks(); + private: + class cChunkData { public: @@ -75,3 +88,7 @@ private: cWorld* m_World; }; + + + + diff --git a/source/cClientHandle.cpp b/source/cClientHandle.cpp index 898e04e72..1019f26c6 100644 --- a/source/cClientHandle.cpp +++ b/source/cClientHandle.cpp @@ -221,14 +221,14 @@ cClientHandle::~cClientHandle() void cClientHandle::Destroy() { - m_bDestroyed = true; - if (m_Socket.IsValid()) - { - m_Socket.CloseSocket(); - } - - // Synchronize with the cSocketThreads (so that they don't call us anymore) - cRoot::Get()->GetServer()->ClientDestroying(this); + m_bDestroyed = true; + if (m_Socket.IsValid()) + { + m_Socket.CloseSocket(); + } + + // Synchronize with the cSocketThreads (so that they don't call us anymore) + cRoot::Get()->GetServer()->ClientDestroying(this); } @@ -237,6 +237,7 @@ void cClientHandle::Destroy() void cClientHandle::Kick(const AString & a_Reason) { + LOG("Kicking user \"%s\" for \"%s\"", m_Username.c_str(), a_Reason.c_str()); Send(cPacket_Disconnect(a_Reason)); m_bKicking = true; } @@ -512,10 +513,10 @@ void cClientHandle::HandleHandshake(cPacket_Handshake * a_Packet) cPacket_Chat Connecting(m_Username + " is connecting."); cRoot::Get()->GetServer()->Broadcast(Connecting, this); - // Give a server handshake thingy back cPacket_Handshake Handshake; Handshake.m_Username = cRoot::Get()->GetServer()->GetServerID(); Send(Handshake); + LOG("User \"%s\" was sent a handshake", m_Username.c_str()); } diff --git a/source/cRoot.cpp b/source/cRoot.cpp index 0ccee5f20..273bbe318 100644 --- a/source/cRoot.cpp +++ b/source/cRoot.cpp @@ -162,7 +162,7 @@ void cRoot::LoadWorlds() cIniFile IniFile("settings.ini"); IniFile.ReadFile(); // First get the default world - std::string DefaultWorldName = IniFile.GetValue("Worlds", "DefaultWorld", "world"); + AString DefaultWorldName = IniFile.GetValue("Worlds", "DefaultWorld", "world"); m_pState->pDefaultWorld = new cWorld( DefaultWorldName.c_str() ); m_pState->pDefaultWorld->InitializeSpawn(); m_pState->WorldsByName[ DefaultWorldName ] = m_pState->pDefaultWorld; diff --git a/source/cWorld.cpp b/source/cWorld.cpp index c54347dcd..ba103c906 100644 --- a/source/cWorld.cpp +++ b/source/cWorld.cpp @@ -114,6 +114,10 @@ cWorld* cWorld::GetWorld() return cRoot::Get()->GetWorld(); } + + + + cWorld::~cWorld() { LockEntities(); @@ -144,6 +148,10 @@ cWorld::~cWorld() delete m_WorldGenerator; } + + + + cWorld::cWorld( const char* a_WorldName ) : m_pState( new sWorldState ) , m_SpawnMonsterTime( 0.f ) @@ -343,9 +351,12 @@ cWorld::cWorld( const char* a_WorldName ) g_BlockPistonBreakable[ E_BLOCK_VINES ] = true; g_BlockPistonBreakable[ E_BLOCK_STONE_PRESSURE_PLATE ] = true; g_BlockPistonBreakable[ E_BLOCK_WOODEN_PRESSURE_PLATE ] = true; - } + + + + void cWorld::SetWeather( int Weather ) { if (Weather == 2) { //thunder storm @@ -377,6 +388,10 @@ void cWorld::CastThunderbolt ( int X, int Y, int Z ) { Broadcast( ThunderboltPacket ); } + + + + void cWorld::InitializeSpawn() { int ChunkX = 0, ChunkY = 0, ChunkZ = 0; @@ -393,6 +408,10 @@ void cWorld::InitializeSpawn() } } + + + + void cWorld::Tick(float a_Dt) { int randWeather = 0; @@ -445,47 +464,13 @@ void cWorld::Tick(float a_Dt) LOGWARN("Lots of lighting to do! At least %i chunks left!", m_pState->SpreadQueue.size() ); } - m_ChunkMap->Tick(a_Dt); + m_ChunkMap->Tick(a_Dt, m_TickRand); GetSimulatorManager()->Simulate(a_Dt); UnlockChunks(); - MTRand r1; - -////////////////Weather/////////////////////// - if ( GetWeather() == 0 ) { //if sunny - if( CurrentTick % 19 == 0 ) { //every 20 ticks random weather - randWeather = (r1.randInt() %10000); - if (randWeather == 0) { - LOG("Starting Rainstorm!"); - SetWeather ( 1 ); - } else if (randWeather == 1) { - LOG("Starting Thunderstorm!"); - SetWeather ( 2 ); - } - } - } - - if ( GetWeather() != 0 ) { //if raining or thunderstorm - if( CurrentTick % 19 == 0 ) { //every 20 ticks random weather - randWeather = (r1.randInt() %4999); - if (randWeather == 0) { //2% chance per second - LOG("Back to sunny!"); - SetWeather ( 0 ); - } else if ( (randWeather > 4000) && (GetWeather() != 2) ) { //random chance for rainstorm to turn into thunderstorm. - LOG("Starting Thunderstorm!"); - SetWeather ( 2 ); - } - } - } - - if ( GetWeather() == 2 ) { //if thunderstorm - if (r1.randInt() %199 == 0) { //0.5% chance per tick of thunderbolt - CastThunderbolt ( 0, 0, 0 ); //todo: find random possitions near players to cast thunderbolts. - } - } -////////////////Weather/////////////////////// + TickWeather(a_Dt); // Asynchronously set blocks FastSetBlockList FastSetBlockQueueCopy = m_pState->FastSetBlockQueue; @@ -521,17 +506,17 @@ void cWorld::Tick(float a_Dt) cMonster *Monster = 0; //srand ( time(NULL) ); // Only seed random ONCE! Is already done in the cWorld constructor - int dayRand = r1.randInt() % 6; //added mob code - int nightRand = r1.randInt() % 10; //added mob code + int dayRand = m_TickRand.randInt() % 6; //added mob code + int nightRand = m_TickRand.randInt() % 10; //added mob code - int RandomPlayerIdx = r1.randInt() & m_pState->Players.size(); + int RandomPlayerIdx = m_TickRand.randInt() & m_pState->Players.size(); PlayerList::iterator itr = m_pState->Players.begin(); for( int i = 1; i < RandomPlayerIdx; i++ ) itr++; cPlayer* Player = *itr; Vector3d SpawnPos = Player->GetPosition(); - SpawnPos += Vector3d( (double)(r1.randInt()%64)-32, (double)(r1.randInt()%64)-32, (double)(r1.randInt()%64)-32 ); + SpawnPos += Vector3d( (double)(m_TickRand.randInt()%64)-32, (double)(m_TickRand.randInt()%64)-32, (double)(m_TickRand.randInt()%64)-32 ); char Height = GetHeight( (int)SpawnPos.x, (int)SpawnPos.z ); if(m_WorldTime >= 12000 + 1000) { @@ -582,7 +567,6 @@ void cWorld::Tick(float a_Dt) } - std::vector m_RSList_copy(m_RSList); //copy(m_RSList.begin(), m_RSList.end(), m_RSList_copy.begin()); m_RSList.erase(m_RSList.begin(),m_RSList.end()); @@ -615,6 +599,62 @@ void cWorld::Tick(float a_Dt) } + + + + +void cWorld::TickWeather(float a_Dt) +{ + ////////////////Weather/////////////////////// + if ( GetWeather() == 0 ) // if sunny + { + if( CurrentTick % 19 == 0 ) //every 20 ticks random weather + { + unsigned randWeather = (m_TickRand.randInt() % 10000); + if (randWeather == 0) + { + LOG("Starting Rainstorm!"); + SetWeather ( 1 ); + } + else if (randWeather == 1) + { + LOG("Starting Thunderstorm!"); + SetWeather ( 2 ); + } + } + } + + if ( GetWeather() != 0 ) // if raining or thunderstorm + { + if ( CurrentTick % 19 == 0 ) // every 20 ticks random weather + { + unsigned randWeather = (m_TickRand.randInt() % 4999); + if (randWeather == 0) //2% chance per second + { + LOG("Back to sunny!"); + SetWeather ( 0 ); + } + else if ( (randWeather > 4000) && (GetWeather() != 2) ) // random chance for rainstorm to turn into thunderstorm. + { + LOG("Starting Thunderstorm!"); + SetWeather ( 2 ); + } + } + } + + if ( GetWeather() == 2 ) // if thunderstorm + { + if (m_TickRand.randInt() % 199 == 0) // 0.5% chance per tick of thunderbolt + { + CastThunderbolt ( 0, 0, 0 ); // todo: find random possitions near players to cast thunderbolts. + } + } +} + + + + + void cWorld::GrowTree( int a_X, int a_Y, int a_Z ) { // new tree code, looks much better diff --git a/source/cWorld.h b/source/cWorld.h index c5d036141..e81d3e1df 100644 --- a/source/cWorld.h +++ b/source/cWorld.h @@ -1,3 +1,4 @@ + #pragma once #ifndef _WIN32 @@ -10,6 +11,7 @@ enum ENUM_ITEM_ID; #include "cSimulatorManager.h" #include "ptr_cChunk.h" +#include "MersenneTwister.h" @@ -23,7 +25,6 @@ class cLavaSimulator; class cSandSimulator; class cChunkMap; class cItem; -class cCriticalSection; class cPlayer; class cClientHandle; class cChunk; @@ -159,17 +160,19 @@ public: int GetWeather() { return m_Weather; }; //tolua_export cWorldGenerator* GetWorldGenerator() { return m_WorldGenerator; } + private: + friend class cRoot; + cWorld( const char* a_WorldName ); ~cWorld(); struct sWorldState; sWorldState* m_pState; - - void AddToRemoveEntityQueue( cEntity & a_Entity ); - void RemoveEntity( cEntity* a_Entity ); - void UnloadUnusedChunks(); + + // 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; double m_SpawnX; double m_SpawnY; @@ -206,4 +209,15 @@ private: unsigned int m_WorldSeed; int m_Weather; + + void TickWeather(float a_Dt); // Handles weather each tick + + void AddToRemoveEntityQueue( cEntity & a_Entity ); + void RemoveEntity( cEntity* a_Entity ); + void UnloadUnusedChunks(); + }; //tolua_export + + + + -- cgit v1.2.3