From 4cebaa99f88e25e039416354cf490fe98642af7e Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Thu, 1 Nov 2012 21:38:20 +0000 Subject: Refactored the world time. Now it is stored in two values - WorldAge (only incremented, plugins cannot change) and TimeOfDay (plugins can change). Since sub-tick precision is needed in Tick(), we store it both as number of seconds (double) and number of ticks (Int64) is calculated off of that. git-svn-id: http://mc-server.googlecode.com/svn/trunk@1022 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- MCServer/Plugins/Core/time.lua | 4 +- source/AllToLua.pkg | 10 ++ source/Bindings.cpp | 200 ++++++++++++++++++++++++++++++--- source/Bindings.h | 2 +- source/ClientHandle.cpp | 17 +-- source/ClientHandle.h | 5 +- source/Mobs/Cavespider.cpp | 2 +- source/Mobs/Enderman.cpp | 5 +- source/Mobs/Monster.cpp | 4 +- source/Mobs/Skeleton.cpp | 7 +- source/Mobs/Zombie.cpp | 5 +- source/Mobs/Zombiepigman.cpp | 5 +- source/Pawn.cpp | 2 +- source/Pawn.h | 2 +- source/Player.cpp | 10 +- source/Protocol/Protocol.h | 2 +- source/Protocol/Protocol125.cpp | 5 +- source/Protocol/Protocol125.h | 2 +- source/Protocol/Protocol142.cpp | 11 +- source/Protocol/Protocol142.h | 2 +- source/Protocol/ProtocolRecognizer.cpp | 4 +- source/Protocol/ProtocolRecognizer.h | 2 +- source/World.cpp | 97 +++++++--------- source/World.h | 61 +++++++--- 24 files changed, 328 insertions(+), 138 deletions(-) diff --git a/MCServer/Plugins/Core/time.lua b/MCServer/Plugins/Core/time.lua index 425d69e6a..8515972a6 100644 --- a/MCServer/Plugins/Core/time.lua +++ b/MCServer/Plugins/Core/time.lua @@ -6,10 +6,10 @@ function HandleTimeCommand( Split, Player ) local Server = cRoot:Get():GetServer() if( string.upper( Split[2] ) == "DAY") then - Player:GetWorld():SetWorldTime( 0 ) + Player:GetWorld():SetTimeOfDay( 0 ) Server:SendMessage( cChatColor.Green .. Player:GetName() .. " set the time to Day.") elseif( string.upper( Split[2] ) == "NIGHT") then - Player:GetWorld():SetWorldTime( 12000 + 1000 ) + Player:GetWorld():SetTimeOfDay( 12000 + 1000 ) Server:SendMessage( cChatColor.Green .. Player:GetName() .. " set the time to Night.") else Player:SendMessage( cChatColor.Green .. "Usage: /time [Day/Night]" ) diff --git a/source/AllToLua.pkg b/source/AllToLua.pkg index 0913de9a2..dea5dc54f 100644 --- a/source/AllToLua.pkg +++ b/source/AllToLua.pkg @@ -3,6 +3,16 @@ $#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same acr $#include "tolua_base.h" +// Typedefs from Globals.h, so that we don't have to include that file: +typedef long long Int64; +typedef int Int32; +typedef short Int16; + +typedef unsigned long long UInt64; +typedef unsigned int UInt32; +typedef unsigned short UInt16; + + $cfile "ChunkDef.h" $cfile "Torch.h" diff --git a/source/Bindings.cpp b/source/Bindings.cpp index 3c1db8d54..40c5d719a 100644 --- a/source/Bindings.cpp +++ b/source/Bindings.cpp @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 10/31/12 20:34:13. +** Generated automatically by tolua++-1.0.92 on 11/01/12 22:24:07. */ #ifndef __cplusplus @@ -11397,6 +11397,168 @@ static int tolua_AllToLua_cWorld_GetTime00(lua_State* tolua_S) } #endif //#ifndef TOLUA_DISABLE +/* method: GetWorldTime of class cWorld */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_GetWorldTime00 +static int tolua_AllToLua_cWorld_GetWorldTime00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cWorld",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cWorld* self = (const cWorld*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetWorldTime'", NULL); +#endif + { + long long tolua_ret = (long long) self->GetWorldTime(); + tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'GetWorldTime'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: GetWorldAge of class cWorld */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_GetWorldAge00 +static int tolua_AllToLua_cWorld_GetWorldAge00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cWorld",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cWorld* self = (const cWorld*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetWorldAge'", NULL); +#endif + { + long long tolua_ret = ( long long) self->GetWorldAge(); + tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'GetWorldAge'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: GetTimeOfDay of class cWorld */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_GetTimeOfDay00 +static int tolua_AllToLua_cWorld_GetTimeOfDay00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"const cWorld",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const cWorld* self = (const cWorld*) tolua_tousertype(tolua_S,1,0); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetTimeOfDay'", NULL); +#endif + { + long long tolua_ret = ( long long) self->GetTimeOfDay(); + tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); + } + } + return 1; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'GetTimeOfDay'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: SetTimeOfDay of class cWorld */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_SetTimeOfDay00 +static int tolua_AllToLua_cWorld_SetTimeOfDay00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"cWorld",0,&tolua_err) || + !tolua_isnumber(tolua_S,2,0,&tolua_err) || + !tolua_isnoobj(tolua_S,3,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cWorld* self = (cWorld*) tolua_tousertype(tolua_S,1,0); + long long a_TimeOfDay = (( long long) tolua_tonumber(tolua_S,2,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetTimeOfDay'", NULL); +#endif + { + self->SetTimeOfDay(a_TimeOfDay); + } + } + return 0; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'SetTimeOfDay'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + +/* method: SetWorldTime of class cWorld */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_SetWorldTime00 +static int tolua_AllToLua_cWorld_SetWorldTime00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isusertype(tolua_S,1,"cWorld",0,&tolua_err) || + !tolua_isnumber(tolua_S,2,0,&tolua_err) || + !tolua_isnoobj(tolua_S,3,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + cWorld* self = (cWorld*) tolua_tousertype(tolua_S,1,0); + long long a_TimeOfDay = ((long long) tolua_tonumber(tolua_S,2,0)); +#ifndef TOLUA_RELEASE + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetWorldTime'", NULL); +#endif + { + self->SetWorldTime(a_TimeOfDay); + } + } + return 0; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'SetWorldTime'.",&tolua_err); + return 0; +#endif +} +#endif //#ifndef TOLUA_DISABLE + /* method: GetGameMode of class cWorld */ #ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_GetGameMode00 static int tolua_AllToLua_cWorld_GetGameMode00(lua_State* tolua_S) @@ -11461,34 +11623,33 @@ static int tolua_AllToLua_cWorld_IsPVPEnabled00(lua_State* tolua_S) } #endif //#ifndef TOLUA_DISABLE -/* method: SetWorldTime of class cWorld */ -#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_SetWorldTime00 -static int tolua_AllToLua_cWorld_SetWorldTime00(lua_State* tolua_S) +/* method: IsDeepSnowEnabled of class cWorld */ +#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_IsDeepSnowEnabled00 +static int tolua_AllToLua_cWorld_IsDeepSnowEnabled00(lua_State* tolua_S) { #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( - !tolua_isusertype(tolua_S,1,"cWorld",0,&tolua_err) || - !tolua_isnumber(tolua_S,2,0,&tolua_err) || - !tolua_isnoobj(tolua_S,3,&tolua_err) + !tolua_isusertype(tolua_S,1,"const cWorld",0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) ) goto tolua_lerror; else #endif { - cWorld* self = (cWorld*) tolua_tousertype(tolua_S,1,0); - long long a_WorldTime = ((long long) tolua_tonumber(tolua_S,2,0)); + const cWorld* self = (const cWorld*) tolua_tousertype(tolua_S,1,0); #ifndef TOLUA_RELEASE - if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetWorldTime'", NULL); + if (!self) tolua_error(tolua_S,"invalid 'self' in function 'IsDeepSnowEnabled'", NULL); #endif { - self->SetWorldTime(a_WorldTime); + bool tolua_ret = (bool) self->IsDeepSnowEnabled(); + tolua_pushboolean(tolua_S,(bool)tolua_ret); } } - return 0; + return 1; #ifndef TOLUA_RELEASE tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'SetWorldTime'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'IsDeepSnowEnabled'.",&tolua_err); return 0; #endif } @@ -11511,13 +11672,13 @@ static int tolua_AllToLua_cWorld_GetHeight00(lua_State* tolua_S) #endif { cWorld* self = (cWorld*) tolua_tousertype(tolua_S,1,0); - int a_X = ((int) tolua_tonumber(tolua_S,2,0)); - int a_Z = ((int) tolua_tonumber(tolua_S,3,0)); + int a_BlockX = ((int) tolua_tonumber(tolua_S,2,0)); + int a_BlockZ = ((int) tolua_tonumber(tolua_S,3,0)); #ifndef TOLUA_RELEASE if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetHeight'", NULL); #endif { - int tolua_ret = (int) self->GetHeight(a_X,a_Z); + int tolua_ret = (int) self->GetHeight(a_BlockX,a_BlockZ); tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); } } @@ -23031,9 +23192,14 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_cclass(tolua_S,"cWorld","cWorld","",NULL); tolua_beginmodule(tolua_S,"cWorld"); tolua_function(tolua_S,"GetTime",tolua_AllToLua_cWorld_GetTime00); + tolua_function(tolua_S,"GetWorldTime",tolua_AllToLua_cWorld_GetWorldTime00); + tolua_function(tolua_S,"GetWorldAge",tolua_AllToLua_cWorld_GetWorldAge00); + tolua_function(tolua_S,"GetTimeOfDay",tolua_AllToLua_cWorld_GetTimeOfDay00); + tolua_function(tolua_S,"SetTimeOfDay",tolua_AllToLua_cWorld_SetTimeOfDay00); + tolua_function(tolua_S,"SetWorldTime",tolua_AllToLua_cWorld_SetWorldTime00); tolua_function(tolua_S,"GetGameMode",tolua_AllToLua_cWorld_GetGameMode00); tolua_function(tolua_S,"IsPVPEnabled",tolua_AllToLua_cWorld_IsPVPEnabled00); - tolua_function(tolua_S,"SetWorldTime",tolua_AllToLua_cWorld_SetWorldTime00); + tolua_function(tolua_S,"IsDeepSnowEnabled",tolua_AllToLua_cWorld_IsDeepSnowEnabled00); tolua_function(tolua_S,"GetHeight",tolua_AllToLua_cWorld_GetHeight00); tolua_function(tolua_S,"UnloadUnusedChunks",tolua_AllToLua_cWorld_UnloadUnusedChunks00); tolua_function(tolua_S,"GetMaxPlayers",tolua_AllToLua_cWorld_GetMaxPlayers00); diff --git a/source/Bindings.h b/source/Bindings.h index 16b1b02a6..42e495fe5 100644 --- a/source/Bindings.h +++ b/source/Bindings.h @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 10/31/12 20:34:14. +** Generated automatically by tolua++-1.0.92 on 11/01/12 22:24:07. */ /* Exported function */ diff --git a/source/ClientHandle.cpp b/source/ClientHandle.cpp index a6e025f8c..24654d303 100644 --- a/source/ClientHandle.cpp +++ b/source/ClientHandle.cpp @@ -81,7 +81,7 @@ cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance) , m_bDestroyed(false) , m_Player(NULL) , m_bKicking(false) - , m_TimeLastPacket(cWorld::GetTime()) + , m_TimeSinceLastPacket(0) , m_bKeepThreadGoing(true) , m_Ping(1000) , m_PingID(1) @@ -244,7 +244,7 @@ void cClientHandle::Authenticate(void) } // Send time - m_Protocol->SendTimeUpdate(World->GetWorldTime()); + m_Protocol->SendTimeUpdate(World->GetWorldAge(), World->GetTimeOfDay()); // Send inventory m_Player->GetInventory().SendWholeInventory(*this); @@ -1049,6 +1049,8 @@ bool cClientHandle::CheckBlockInteractionsRate(void) { ASSERT(m_Player != NULL); ASSERT(m_Player->GetWorld() != NULL); + /* + // TODO: _X 2012_11_01: This needs a total re-thinking and rewriting int LastActionCnt = m_Player->GetLastBlockActionCnt(); if ((m_Player->GetWorld()->GetTime() - m_Player->GetLastBlockActionTime()) < 0.1) { @@ -1068,6 +1070,7 @@ bool cClientHandle::CheckBlockInteractionsRate(void) m_Player->SetLastBlockActionCnt(0); // Reset count m_Player->SetLastBlockActionTime(); // Player tried to interact with a block. Reset last block interation time. } + */ return true; } @@ -1077,8 +1080,8 @@ bool cClientHandle::CheckBlockInteractionsRate(void) void cClientHandle::Tick(float a_Dt) { - (void)a_Dt; - if (cWorld::GetTime() - m_TimeLastPacket > 30.f) // 30 seconds time-out + m_TimeSinceLastPacket += a_Dt; + if (m_TimeSinceLastPacket > 30000.f) // 30 seconds time-out { SendDisconnect("Nooooo!! You timed out! D: Come back!"); Destroy(); @@ -1459,9 +1462,9 @@ void cClientHandle::SendWeather(eWeather a_Weather) -void cClientHandle::SendTimeUpdate(Int64 a_WorldTime) +void cClientHandle::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay) { - m_Protocol->SendTimeUpdate(a_WorldTime); + m_Protocol->SendTimeUpdate(a_WorldAge, a_TimeOfDay); } @@ -1704,7 +1707,7 @@ void cClientHandle::DataReceived(const char * a_Data, int a_Size) { // Data is received from the client, hand it off to the protocol: m_Protocol->DataReceived(a_Data, a_Size); - m_TimeLastPacket = cWorld::GetTime(); + m_TimeSinceLastPacket = 0; } diff --git a/source/ClientHandle.h b/source/ClientHandle.h index c3b8ec731..a9a372186 100644 --- a/source/ClientHandle.h +++ b/source/ClientHandle.h @@ -110,7 +110,7 @@ public: void SendSpawnMob (const cMonster & a_Mob); void SendTeleportEntity (const cEntity & a_Entity); void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ); - void SendTimeUpdate (Int64 a_WorldTime); + void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay); void SendUnloadChunk (int a_ChunkX, int a_ChunkZ); void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4); void SendWeather (eWeather a_Weather); @@ -207,7 +207,8 @@ private: int m_LastStreamedChunkX; int m_LastStreamedChunkZ; - float m_TimeLastPacket; + /// Seconds since the last packet data was received (updated in Tick(), reset in DataReceived()) + float m_TimeSinceLastPacket; short m_Ping; int m_PingID; diff --git a/source/Mobs/Cavespider.cpp b/source/Mobs/Cavespider.cpp index b2188da3d..6c7ed0a7a 100644 --- a/source/Mobs/Cavespider.cpp +++ b/source/Mobs/Cavespider.cpp @@ -38,7 +38,7 @@ bool cCavespider::IsA( const char* a_EntityType ) void cCavespider::Tick(float a_Dt) { cMonster::Tick(a_Dt); - m_EMPersonality = (GetWorld()->GetWorldTime() < (12000 + 1000) ) ? PASSIVE : AGGRESSIVE; + m_EMPersonality = (GetWorld()->GetTimeOfDay() < (12000 + 1000)) ? PASSIVE : AGGRESSIVE; } diff --git a/source/Mobs/Enderman.cpp b/source/Mobs/Enderman.cpp index 36ee975b1..216fab85f 100644 --- a/source/Mobs/Enderman.cpp +++ b/source/Mobs/Enderman.cpp @@ -39,8 +39,9 @@ void cEnderman::Tick(float a_Dt) { cMonster::Tick(a_Dt); - //TODO Same as stated in cSkeleton - if (GetWorld()->GetWorldTime() < (12000 + 1000) && GetMetaData() != BURNING) { //if daylight + // TODO Same as stated in cSkeleton + if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && (GetMetaData() != BURNING)) + { SetMetaData(BURNING); // BURN, BABY, BURN! >:D } } diff --git a/source/Mobs/Monster.cpp b/source/Mobs/Monster.cpp index 6a5a2d667..82d69df57 100644 --- a/source/Mobs/Monster.cpp +++ b/source/Mobs/Monster.cpp @@ -217,12 +217,12 @@ void cMonster::ReplicateMovement() float SqrDist = DiffX * DiffX + DiffY * DiffY + DiffZ * DiffZ; if ( (SqrDist > 4 * 4) // 4 blocks is max Relative Move - || (cWorld::GetTime() - m_TimeLastTeleportPacket > 2) // Send an absolute position every 2 seconds + || (m_World->GetWorldAge() - m_TimeLastTeleportPacket > 40) // Send an absolute position every 2 seconds ) { // LOGD("Teleported %f", sqrtf(SqrDist) ); m_World->BroadcastTeleportEntity(*this); - m_TimeLastTeleportPacket = cWorld::GetTime(); + m_TimeLastTeleportPacket = m_World->GetWorldAge(); } else { diff --git a/source/Mobs/Skeleton.cpp b/source/Mobs/Skeleton.cpp index 56bbb9310..b35cdb68e 100644 --- a/source/Mobs/Skeleton.cpp +++ b/source/Mobs/Skeleton.cpp @@ -39,9 +39,10 @@ void cSkeleton::Tick(float a_Dt) { cMonster::Tick(a_Dt); - //TODO Outsource - //TODO should do lightcheck, not daylight -> mobs in the dark donīt burn - if (GetWorld()->GetWorldTime() < (12000 + 1000) && GetMetaData() != BURNING ) { //if daylight + // TODO Outsource + // TODO should do SkyLight check, mobs in the dark donīt burn + if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && (GetMetaData() != BURNING)) + { SetMetaData(BURNING); // BURN, BABY, BURN! >:D } } diff --git a/source/Mobs/Zombie.cpp b/source/Mobs/Zombie.cpp index b51931904..b0a429f25 100644 --- a/source/Mobs/Zombie.cpp +++ b/source/Mobs/Zombie.cpp @@ -39,8 +39,9 @@ void cZombie::Tick(float a_Dt) { cMonster::Tick(a_Dt); - //TODO Same as in cSkeleton :D - if (GetWorld()->GetWorldTime() < (12000 + 1000) && GetMetaData() != BURNING) { //if daylight + // TODO Same as in cSkeleton :D + if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && (GetMetaData() != BURNING)) + { SetMetaData(BURNING); // BURN, BABY, BURN! >:D } } diff --git a/source/Mobs/Zombiepigman.cpp b/source/Mobs/Zombiepigman.cpp index 65293cfce..a33d78efa 100644 --- a/source/Mobs/Zombiepigman.cpp +++ b/source/Mobs/Zombiepigman.cpp @@ -39,8 +39,9 @@ void cZombiepigman::Tick(float a_Dt) { cMonster::Tick(a_Dt); - //TODO Same as noticed in cSkeleton AND Do they really burn by sun?? :D In the neather is no sun :D - if (GetWorld()->GetWorldTime() < (12000 + 1000) && GetMetaData() != BURNING ) { //if daylight + // TODO Same as noticed in cSkeleton AND Do they really burn by sun?? :D In the neather is no sun :D + if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && (GetMetaData() != BURNING)) + { SetMetaData(BURNING); // BURN, BABY, BURN! >:D } } diff --git a/source/Pawn.cpp b/source/Pawn.cpp index ae8133420..da878bf49 100644 --- a/source/Pawn.cpp +++ b/source/Pawn.cpp @@ -26,7 +26,7 @@ cPawn::cPawn() , m_LastPosX( 0.0 ) , m_LastPosY( 0.0 ) , m_LastPosZ( 0.0 ) - , m_TimeLastTeleportPacket( 0.f ) + , m_TimeLastTeleportPacket(0) , m_bBurnable(true) , m_MetaData(NORMAL) { diff --git a/source/Pawn.h b/source/Pawn.h index 9cc106cc1..cb3381644 100644 --- a/source/Pawn.h +++ b/source/Pawn.h @@ -58,7 +58,7 @@ protected: MetaData m_MetaData; double m_LastPosX, m_LastPosY, m_LastPosZ; - float m_TimeLastTeleportPacket; + Int64 m_TimeLastTeleportPacket; // In ticks }; //tolua_export diff --git a/source/Player.cpp b/source/Player.cpp index 708eca9f4..cf9e4be99 100644 --- a/source/Player.cpp +++ b/source/Player.cpp @@ -79,8 +79,8 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) cTimer t1; m_LastPlayerListTime = t1.GetNowTime(); - m_TimeLastTeleportPacket = cWorld::GetTime(); - m_TimeLastPickupCheck = cWorld::GetTime(); + m_TimeLastTeleportPacket = 0; + m_TimeLastPickupCheck = 0; m_PlayerName = a_PlayerName; m_bDirtyPosition = true; // So chunks are streamed to player at spawn @@ -189,12 +189,12 @@ void cPlayer::Tick(float a_Dt) float SqrDist = DiffX * DiffX + DiffY * DiffY + DiffZ * DiffZ; if ( (SqrDist > 4 * 4) || // 4 blocks is max Relative Move - (cWorld::GetTime() - m_TimeLastTeleportPacket > 2 ) // Send an absolute position every 2 seconds + (m_World->GetWorldAge() - m_TimeLastTeleportPacket > 40) // Send an absolute position every 2 seconds ) { // LOG("Teleported %f", sqrtf(SqrDist) ); m_World->BroadcastTeleportEntity(*this, m_ClientHandle); - m_TimeLastTeleportPacket = cWorld::GetTime(); + m_TimeLastTeleportPacket = m_World->GetWorldAge(); } else { @@ -474,7 +474,7 @@ void cPlayer::SetLastBlockActionTime() { if (m_World != NULL) { - m_LastBlockActionTime = m_World->GetTime(); + m_LastBlockActionTime = m_World->GetWorldAge() / 20.0f; } } diff --git a/source/Protocol/Protocol.h b/source/Protocol/Protocol.h index 50ee2cc51..b2423c6a2 100644 --- a/source/Protocol/Protocol.h +++ b/source/Protocol/Protocol.h @@ -78,7 +78,7 @@ public: virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, short a_SpeedX, short a_SpeedY, short a_SpeedZ) = 0; virtual void SendTeleportEntity (const cEntity & a_Entity) = 0; virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) = 0; - virtual void SendTimeUpdate (Int64 a_WorldTime) = 0; + virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay) = 0; virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) = 0; virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) = 0; virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) = 0; diff --git a/source/Protocol/Protocol125.cpp b/source/Protocol/Protocol125.cpp index 44c97993d..58afcdcae 100644 --- a/source/Protocol/Protocol125.cpp +++ b/source/Protocol/Protocol125.cpp @@ -685,11 +685,12 @@ void cProtocol125::SendThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ) -void cProtocol125::SendTimeUpdate(Int64 a_WorldTime) +void cProtocol125::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay) { cCSLock Lock(m_CSPacket); WriteByte (PACKET_UPDATE_TIME); - WriteInt64(a_WorldTime); + // Use a_WorldAge for daycount, and a_TimeOfDay for the proper time of day: + WriteInt64((24000 * (a_WorldAge / 24000)) + (a_TimeOfDay % 24000)); Flush(); } diff --git a/source/Protocol/Protocol125.h b/source/Protocol/Protocol125.h index 991b28dac..a9c85ae4d 100644 --- a/source/Protocol/Protocol125.h +++ b/source/Protocol/Protocol125.h @@ -62,7 +62,7 @@ public: virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, short a_SpeedX, short a_SpeedY, short a_SpeedZ) override; virtual void SendTeleportEntity (const cEntity & a_Entity) override; virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; - virtual void SendTimeUpdate (Int64 a_WorldTime) override; + virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay) override; virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) override; diff --git a/source/Protocol/Protocol142.cpp b/source/Protocol/Protocol142.cpp index b4b2b66c1..17501169d 100644 --- a/source/Protocol/Protocol142.cpp +++ b/source/Protocol/Protocol142.cpp @@ -91,10 +91,7 @@ void cProtocol142::SendPickupSpawn(const cPickup & a_Pickup) cCSLock Lock(m_CSPacket); WriteByte (PACKET_PICKUP_SPAWN); WriteInt (a_Pickup.GetUniqueID()); - WriteShort (a_Pickup.GetItem()->m_ItemType); - WriteByte (a_Pickup.GetItem()->m_ItemCount); - WriteShort (a_Pickup.GetItem()->m_ItemDamage); - WriteShort (-1); //TODO: Implement item metadata + WriteItem (*(a_Pickup.GetItem())); WriteVectorI((Vector3i)(a_Pickup.GetPosition() * 32)); WriteByte ((char)(a_Pickup.GetSpeed().x * 8)); WriteByte ((char)(a_Pickup.GetSpeed().y * 8)); @@ -123,11 +120,11 @@ void cProtocol142::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_Src -void cProtocol142::SendTimeUpdate(Int64 a_WorldTime) +void cProtocol142::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay) { cCSLock Lock(m_CSPacket); WriteByte (PACKET_UPDATE_TIME); - WriteInt64(1); - WriteInt64(a_WorldTime); + WriteInt64(a_WorldAge); + WriteInt64(a_TimeOfDay); Flush(); } \ No newline at end of file diff --git a/source/Protocol/Protocol142.h b/source/Protocol/Protocol142.h index 8b2205e44..96256044f 100644 --- a/source/Protocol/Protocol142.h +++ b/source/Protocol/Protocol142.h @@ -27,7 +27,7 @@ public: // Sending commands (alphabetically sorted): virtual void SendPickupSpawn (const cPickup & a_Pickup) override; virtual void SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; - virtual void SendTimeUpdate (Int64 a_WorldTime) override; + virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay) override; // Specific packet parsers: virtual int ParseLogin (void) override; diff --git a/source/Protocol/ProtocolRecognizer.cpp b/source/Protocol/ProtocolRecognizer.cpp index 5b266bd34..3d16b42e8 100644 --- a/source/Protocol/ProtocolRecognizer.cpp +++ b/source/Protocol/ProtocolRecognizer.cpp @@ -428,10 +428,10 @@ void cProtocolRecognizer::SendThunderbolt(int a_BlockX, int a_BlockY, int a_Bloc -void cProtocolRecognizer::SendTimeUpdate(Int64 a_WorldTime) +void cProtocolRecognizer::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay) { ASSERT(m_Protocol != NULL); - m_Protocol->SendTimeUpdate(a_WorldTime); + m_Protocol->SendTimeUpdate(a_WorldAge, a_TimeOfDay); } diff --git a/source/Protocol/ProtocolRecognizer.h b/source/Protocol/ProtocolRecognizer.h index fb82502f4..4b7877311 100644 --- a/source/Protocol/ProtocolRecognizer.h +++ b/source/Protocol/ProtocolRecognizer.h @@ -80,7 +80,7 @@ public: virtual void SendSpawnObject (const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, short a_SpeedX, short a_SpeedY, short a_SpeedZ) override; virtual void SendTeleportEntity (const cEntity & a_Entity) override; virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; - virtual void SendTimeUpdate (Int64 a_WorldTime) override; + virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay) override; virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) override; diff --git a/source/World.cpp b/source/World.cpp index 198f32395..29c4f7b5f 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -72,12 +72,6 @@ const int MAX_LIGHTING_SPREAD_PER_TICK = 10; -float cWorld::m_Time = 0.f; - - - - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cWorldLoadProgress: @@ -225,7 +219,12 @@ cWorld::~cWorld() cWorld::cWorld(const AString & a_WorldName) : - m_SpawnMonsterTime(0.f), + m_WorldAgeSecs(0), + m_TimeOfDaySecs(0), + m_WorldAge(0), + m_TimeOfDay(0), + m_LastTimeUpdate(0), + m_LastSpawnMonster(0), m_RSList(0), m_Weather(eWeather_Sunny), m_WeatherInterval(24000) // Guaranteed 1 day of sunshine at server start :) @@ -271,23 +270,22 @@ cWorld::cWorld(const AString & a_WorldName) : m_Generator.Start(this, IniFile); m_bAnimals = true; - m_SpawnMonsterRate = 10; + m_SpawnMonsterRate = 200; // 1 mob each 10 seconds cIniFile IniFile2("settings.ini"); if (IniFile2.ReadFile()) { m_bAnimals = IniFile2.GetValueB("Monsters", "AnimalsOn", true ); - m_SpawnMonsterRate = (float)IniFile2.GetValueF("Monsters", "AnimalSpawnInterval", 10); - SetMaxPlayers(IniFile2.GetValueI("Server", "MaxPlayers", 9001)); - m_Description = IniFile2.GetValue("Server", "Description", "MCServer! - It's OVER 9000!").c_str(); + m_SpawnMonsterRate = (Int64)(IniFile2.GetValueF("Monsters", "AnimalSpawnInterval", 10) * 20); // Convert from secs to ticks + + // TODO: Move this into cServer instead: + SetMaxPlayers(IniFile2.GetValueI("Server", "MaxPlayers", 100)); + m_Description = IniFile2.GetValue("Server", "Description", "MCServer! - In C++!").c_str(); } m_ChunkMap = new cChunkMap(this ); m_ChunkSender.Start(this); - m_Time = 0; - m_WorldTimeFraction = 0.f; - m_WorldTime = 0; m_LastSave = 0; m_LastUnload = 0; @@ -438,23 +436,24 @@ void cWorld::StopThreads(void) void cWorld::Tick(float a_Dt) { - m_Time += a_Dt / 1000.f; + // We need sub-tick precision here, that's why we store the time in seconds and calculate ticks off of it + m_WorldAgeSecs += (double)a_Dt / 1000.0; + m_TimeOfDaySecs += (double)a_Dt / 1000.0; - CurrentTick++; - - bool bSendTime = false; - m_WorldTimeFraction += a_Dt / 1000.f; - while (m_WorldTimeFraction > 1.f) + // Wrap time of day each 20 minutes (1200 seconds) + if (m_TimeOfDaySecs > 1200.0) { - m_WorldTimeFraction -= 1.f; - m_WorldTime += 20; - bSendTime = true; + m_TimeOfDaySecs -= 1200.0; } - m_WorldTime %= 24000; // 24000 units in a day - - if (bSendTime) + + m_WorldAge = (Int64)(m_WorldAgeSecs / 20.0); + m_TimeOfDay = (Int64)(m_TimeOfDaySecs / 20.0); + + // Broadcase time update every 40 ticks (2 seconds) + if (m_LastTimeUpdate < m_WorldAge - 40) { BroadcastTimeUpdate(); + m_LastTimeUpdate = m_WorldAge; } { @@ -496,12 +495,12 @@ void cWorld::Tick(float a_Dt) m_FastSetBlockQueue.splice(m_FastSetBlockQueue.end(), FastSetBlockQueueCopy); } - if( m_Time - m_LastSave > 60 * 5 ) // Save each 5 minutes + if (m_WorldAge - m_LastSave > 60 * 5 * 20) // Save each 5 minutes { SaveAllChunks(); } - if( m_Time - m_LastUnload > 10 ) // Unload every 10 seconds + if (m_WorldAge - m_LastUnload > 10 * 20 ) // Unload every 10 seconds { UnloadUnusedChunks(); } @@ -639,12 +638,12 @@ void cWorld::TickWeather(float a_Dt) void cWorld::TickSpawnMobs(float a_Dt) { - if (!m_bAnimals || (m_Time - m_SpawnMonsterTime <= m_SpawnMonsterRate)) + if (!m_bAnimals || (m_WorldAge - m_LastSpawnMonster <= m_SpawnMonsterRate)) { return; } - m_SpawnMonsterTime = m_Time; + m_LastSpawnMonster = m_WorldAge; Vector3d SpawnPos; { cCSLock Lock(m_CSPlayers); @@ -668,7 +667,7 @@ void cWorld::TickSpawnMobs(float a_Dt) SpawnPos += Vector3d( (double)(m_TickRand.randInt() % 64) - 32, (double)(m_TickRand.randInt() % 64) - 32, (double)(m_TickRand.randInt() % 64) - 32 ); int Height = GetHeight( (int)SpawnPos.x, (int)SpawnPos.z ); - if (m_WorldTime >= 12000 + 1000) + if (m_TimeOfDay >= 12000 + 1000) { if (GetBiomeAt((int)SpawnPos.x, (int)SpawnPos.z) == biHell) // Spawn nether mobs { @@ -796,10 +795,10 @@ void cWorld::GrowTreeFromSapling(int a_X, int a_Y, int a_Z, char a_SaplingMeta) sSetBlockVector Logs, Other; switch (a_SaplingMeta & 0x07) { - case E_META_SAPLING_APPLE: GetAppleTreeImage (a_X, a_Y, a_Z, Noise, (int)(m_WorldTime & 0xffffffff), Logs, Other); break; - case E_META_SAPLING_BIRCH: GetBirchTreeImage (a_X, a_Y, a_Z, Noise, (int)(m_WorldTime & 0xffffffff), Logs, Other); break; - case E_META_SAPLING_CONIFER: GetConiferTreeImage(a_X, a_Y, a_Z, Noise, (int)(m_WorldTime & 0xffffffff), Logs, Other); break; - case E_META_SAPLING_JUNGLE: GetJungleTreeImage (a_X, a_Y, a_Z, Noise, (int)(m_WorldTime & 0xffffffff), Logs, Other); break; + case E_META_SAPLING_APPLE: GetAppleTreeImage (a_X, a_Y, a_Z, Noise, (int)(m_WorldAge & 0xffffffff), Logs, Other); break; + case E_META_SAPLING_BIRCH: GetBirchTreeImage (a_X, a_Y, a_Z, Noise, (int)(m_WorldAge & 0xffffffff), Logs, Other); break; + case E_META_SAPLING_CONIFER: GetConiferTreeImage(a_X, a_Y, a_Z, Noise, (int)(m_WorldAge & 0xffffffff), Logs, Other); break; + case E_META_SAPLING_JUNGLE: GetJungleTreeImage (a_X, a_Y, a_Z, Noise, (int)(m_WorldAge & 0xffffffff), Logs, Other); break; } Other.insert(Other.begin(), Logs.begin(), Logs.end()); Logs.clear(); @@ -814,7 +813,7 @@ void cWorld::GrowTreeByBiome(int a_X, int a_Y, int a_Z) { cNoise Noise(m_Generator.GetSeed()); sSetBlockVector Logs, Other; - GetTreeImageByBiome(a_X, a_Y, a_Z, Noise, (int)(m_WorldTime & 0xffffffff), (EMCSBiome)GetBiomeAt(a_X, a_Z), Logs, Other); + GetTreeImageByBiome(a_X, a_Y, a_Z, Noise, (int)(m_WorldAge & 0xffffffff), (EMCSBiome)GetBiomeAt(a_X, a_Z), Logs, Other); Other.insert(Other.begin(), Logs.begin(), Logs.end()); Logs.clear(); GrowTreeImage(Other); @@ -1440,7 +1439,7 @@ void cWorld::BroadcastTimeUpdate(const cClientHandle * a_Exclude) { continue; } - ch->SendTimeUpdate(m_WorldTime); + ch->SendTimeUpdate(m_WorldAge, m_TimeOfDay); } } @@ -1661,7 +1660,7 @@ bool cWorld::HasChunkAnyClients(int a_ChunkX, int a_ChunkY, int a_ChunkZ) const void cWorld::UnloadUnusedChunks(void ) { - m_LastUnload = m_Time; + m_LastUnload = m_WorldAge; m_ChunkMap->UnloadUnusedChunks(); } @@ -2070,7 +2069,7 @@ bool cWorld::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunk void cWorld::SaveAllChunks(void) { LOGINFO("Saving all chunks..."); - m_LastSave = m_Time; + m_LastSave = m_WorldAge; m_ChunkMap->SaveAllChunks(); m_Storage.QueueSavedMessage(); } @@ -2079,23 +2078,7 @@ void cWorld::SaveAllChunks(void) -/************************************************************************/ -/* Get and set */ -/************************************************************************/ -// void cWorld::AddClient( cClientHandle* a_Client ) -// { -// m_m_Clients.push_back( a_Client ); -// } -// cWorld::ClientList & cWorld::GetClients() -// { -// return m_m_Clients; -// } - - - - - -void cWorld::AddEntity( cEntity* a_Entity ) +void cWorld::AddEntity(cEntity * a_Entity) { cCSLock Lock(m_CSEntities); m_AllEntities.push_back( a_Entity ); @@ -2105,7 +2088,7 @@ void cWorld::AddEntity( cEntity* a_Entity ) -unsigned int cWorld::GetNumPlayers() +unsigned int cWorld::GetNumPlayers(void) { cCSLock Lock(m_CSPlayers); return m_Players.size(); diff --git a/source/World.h b/source/World.h index 7d4b68f23..3b5f45276 100644 --- a/source/World.h +++ b/source/World.h @@ -59,20 +59,43 @@ public: OBSOLETE static cWorld * GetWorld(); - // Return time in seconds - inline static float GetTime() //tolua_export + // tolua_begin + + /// Return time in seconds + inline static float GetTime(void) { - return m_Time; + LOGWARNING("cWorld:GetTime() is obsolete, use GetWorldAge() or GetTimeOfDay() for a specific world instead."); + return 0; } - long long GetWorldTime(void) const { return m_WorldTime; } //tolua_export - - eGameMode GetGameMode(void) const { return m_GameMode; } //tolua_export - bool IsPVPEnabled(void) const { return m_bEnabledPVP; } //tolua_export + + long long GetWorldTime(void) const // OBSOLETE, use GetWorldAge() instead! + { + LOGWARNING("cWorld:GetWorldTime() is obsolete, use GetWorldAge() or GetTimeOfDay() instead"); + return m_WorldAge; + } + Int64 GetWorldAge(void) const { return m_WorldAge; } + Int64 GetTimeOfDay(void) const { return m_TimeOfDay; } + + void SetTimeOfDay(Int64 a_TimeOfDay) + { + m_TimeOfDay = a_TimeOfDay; + m_TimeOfDaySecs = (double)a_TimeOfDay / 20.0; + BroadcastTimeUpdate(); + } + + void SetWorldTime(Int64 a_TimeOfDay) + { + LOGWARNING("cWorld:SetWorldTime() is obsolete, use SetTimeOfDay() instead"); + SetTimeOfDay(a_TimeOfDay); + } + + eGameMode GetGameMode(void) const { return m_GameMode; } + bool IsPVPEnabled(void) const { return m_bEnabledPVP; } bool IsDeepSnowEnabled(void) const { return m_IsDeepSnowEnabled; } - void SetWorldTime(long long a_WorldTime) { m_WorldTime = a_WorldTime; } //tolua_export - - int GetHeight( int a_X, int a_Z ); //tolua_export + int GetHeight(int a_BlockX, int a_BlockZ); + + // tolua_end void BroadcastChat (const AString & a_Message, const cClientHandle * a_Exclude = NULL); void BroadcastPlayerAnimation (const cPlayer & a_Player, char a_Animation, const cClientHandle * a_Exclude = NULL); @@ -422,15 +445,18 @@ private: 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) - unsigned long long CurrentTick; + double m_WorldAgeSecs; // World age, in seconds. Is only incremented, cannot be set by plugins. + double m_TimeOfDaySecs; // Time of day in seconds. Can be adjusted. Is wrapped to zero each day. + Int64 m_WorldAge; // World age in ticks, calculated off of m_WorldAgeSecs + Int64 m_TimeOfDay; // Time in ticks, calculated off of m_TimeOfDaySecs + Int64 m_LastTimeUpdate; // The tick in which the last time update has been sent. + Int64 m_LastUnload; // The last WorldAge (in ticks) in which unloading was triggerred + Int64 m_LastSave; // The last WorldAge (in ticks) in which save-all was triggerred + Int64 m_LastSpawnMonster; // The last WorldAge (in ticks) in which a monster was spawned + eGameMode m_GameMode; bool m_bEnabledPVP; bool m_IsDeepSnowEnabled; - float m_WorldTimeFraction; // When this > 1.f m_WorldTime is incremented by 20 // The cRedstone class simulates redstone and needs access to m_RSList friend class cRedstone; @@ -459,8 +485,7 @@ private: cChunkMap * m_ChunkMap; bool m_bAnimals; - float m_SpawnMonsterTime; - float m_SpawnMonsterRate; + Int64 m_SpawnMonsterRate; eWeather m_Weather; int m_WeatherInterval; -- cgit v1.2.3