From 5b2ac381b63c199ac5150a5d058cde9d30ca9182 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 22 Dec 2013 00:30:21 +0000 Subject: [PATCH 01/19] Fixed them again, confound it --- src/Simulator/RedstoneSimulator.cpp | 30 ++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp index e53c7c172..549c709f6 100644 --- a/src/Simulator/RedstoneSimulator.cpp +++ b/src/Simulator/RedstoneSimulator.cpp @@ -206,10 +206,6 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c itr = m_RepeatersDelayList.erase(itr); continue; } - else if (itr->a_ElapsedTicks < itr->a_DelayTicks) - { - itr->a_ElapsedTicks++; - } itr++; } @@ -659,8 +655,14 @@ void cRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_BlockY, int return; } } - - // Tick incrementing handled in SimChunk + else + { + // Apparently, incrementing ticks only works reliably here, and not in SimChunk; + // With a world with lots of redstone, the repeaters simply do not delay + // I am confounded to say why. Perhaps optimisation failure. + LOGD("Incremented a repeater @ %i %i %i | Elapsed ticks: %i | Target delay: %i", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z, itr->a_ElapsedTicks, itr->a_DelayTicks); + itr->a_ElapsedTicks++; + } } } @@ -897,7 +899,16 @@ void cRedstoneSimulator::HandleNoteBlock(int a_BlockX, int a_BlockY, int a_Block void cRedstoneSimulator::HandleDaylightSensor(int a_BlockX, int a_BlockY, int a_BlockZ) { - if (m_World.GetBlockSkyLight(a_BlockX, a_BlockY + 1, a_BlockZ) > 10) + for (int Y = a_BlockY + 1; Y < 10; Y++) + { + if (!g_BlockTransparent[m_World.GetBlock(a_BlockX, Y, a_BlockZ)]) + { + return; + } + } + + LOG("%i", m_World.GetSkyDarkness()); + if (m_World.GetSkyDarkness() > 10) { SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_DAYLIGHT_SENSOR); } @@ -1318,7 +1329,7 @@ void cRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, in } // Already in here (normal to allow repeater to continue on powering and updating blocks in front) - just update info and quit - itr->a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2; // See below for description + itr->a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + (ShouldPowerOn ? 1 : 0)) * 2; // See below for description itr->a_ElapsedTicks = 0; itr->ShouldPowerOn = ShouldPowerOn; return; @@ -1331,7 +1342,8 @@ void cRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, in // Gets the top two bits (delay time), shifts them into the lower two bits, and adds one (meta 0 = 1 tick; 1 = 2 etc.) // * 2 because apparently, MCS ticks are way faster than vanilla ticks, so repeater aren't noticeably delayed - RC.a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2; + // We don't +1 when powering off because everything seems to already delay a tick when powering off, why? No idea :P + RC.a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + (ShouldPowerOn ? 1 : 0)) * 2; RC.a_ElapsedTicks = 0; From acb5a36a6aa3be861e84b7abc542b6223c55cddd Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 22 Dec 2013 00:33:22 +0000 Subject: [PATCH 02/19] Daylight sensors --- src/Simulator/RedstoneSimulator.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp index 549c709f6..10b750aeb 100644 --- a/src/Simulator/RedstoneSimulator.cpp +++ b/src/Simulator/RedstoneSimulator.cpp @@ -907,8 +907,7 @@ void cRedstoneSimulator::HandleDaylightSensor(int a_BlockX, int a_BlockY, int a_ } } - LOG("%i", m_World.GetSkyDarkness()); - if (m_World.GetSkyDarkness() > 10) + if (m_World.GetSkyDarkness() < 8) { SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_DAYLIGHT_SENSOR); } From 945ba36d1b7b1b90028148aa5637f9842858af12 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 22 Dec 2013 20:03:09 +0000 Subject: [PATCH 03/19] Implemented fall particles --- src/Entities/Player.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 8f30cd4cc..aedd3b77e 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -247,6 +247,9 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) m_World->SendPlayerList(this); m_LastPlayerListTime = t1.GetNowTime(); } + + if (IsFlying()) + m_LastGroundHeight = (float)GetPosY(); } @@ -447,10 +450,19 @@ void cPlayer::SetTouchGround(bool a_bTouchGround) if (m_LastJumpHeight > m_LastGroundHeight) Damage++; m_LastJumpHeight = (float)GetPosY(); - if ((Damage > 0) && (!IsGameModeCreative())) + if (Damage > 0) { - TakeDamage(dtFalling, NULL, Damage, Damage, 0); - } + if (!IsGameModeCreative()) + { + TakeDamage(dtFalling, NULL, Damage, Damage, 0); + } + + GetWorld()->BroadcastSoundParticleEffect( + 2006, + (int)GetPosX(), (int)GetPosY() - 1, (int)GetPosZ(), + Damage // Used as particle effect speed modifier + ); + } m_LastGroundHeight = (float)GetPosY(); } @@ -974,6 +986,9 @@ void cPlayer::SetGameMode(eGameMode a_GameMode) m_GameMode = a_GameMode; m_ClientHandle->SendGameMode(a_GameMode); + + SetFlying(false); + SetCanFly(false); } From 43e819630910e80f4420f15baad3d5322b54b0b3 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 22 Dec 2013 20:03:58 +0000 Subject: [PATCH 04/19] Added many event catchers * Window close * CTRL-C * etc. --- src/Root.cpp | 34 ++++++++++++++++++++-------- src/main.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 78 insertions(+), 20 deletions(-) diff --git a/src/Root.cpp b/src/Root.cpp index fffd8fb47..798f965be 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -22,6 +22,7 @@ #include "inifile/iniFile.h" #ifdef _WIN32 + #include "conio.h" #include #elif defined(__linux__) #include @@ -29,6 +30,8 @@ #include #endif +extern bool g_TERMINATE_EVENT_RAISED; + @@ -76,7 +79,7 @@ void cRoot::InputThread(void * a_Params) cLogCommandOutputCallback Output; - while (!(self.m_bStop || self.m_bRestart) && std::cin.good()) + while (!self.m_bStop && !self.m_bRestart && !g_TERMINATE_EVENT_RAISED && std::cin.good()) { AString Command; std::getline(std::cin, Command); @@ -85,10 +88,10 @@ void cRoot::InputThread(void * a_Params) self.ExecuteConsoleCommand(TrimString(Command), Output); } } - - if (!(self.m_bStop || self.m_bRestart)) + + if (g_TERMINATE_EVENT_RAISED || !std::cin.good()) { - // We have come here because the std::cin has received an EOF and the server is still running; stop the server: + // We have come here because the std::cin has received an EOF / a terminate signal has been sent, and the server is still running; stop the server: self.m_bStop = true; } } @@ -99,6 +102,12 @@ void cRoot::InputThread(void * a_Params) void cRoot::Start(void) { + #ifdef _WIN32 + HWND hwnd = GetConsoleWindow(); + HMENU hmenu = GetSystemMenu(hwnd, FALSE); + EnableMenuItem(hmenu, SC_CLOSE, MF_GRAYED); // Disable close button when starting up; it causes problems with our CTRL-CLOSE handling + #endif + cDeadlockDetect dd; delete m_Log; m_Log = new cMCLogger(); @@ -192,12 +201,20 @@ void cRoot::Start(void) finishmseconds -= mseconds; LOG("Startup complete, took %i ms!", finishmseconds); + #ifdef _WIN32 + EnableMenuItem(hmenu, SC_CLOSE, MF_ENABLED); // Re-enable close button + #endif - while (!m_bStop && !m_bRestart) // These are modified by external threads + while (!m_bStop && !m_bRestart && !g_TERMINATE_EVENT_RAISED) // These are modified by external threads { cSleep::MilliSleep(1000); } + if (g_TERMINATE_EVENT_RAISED) + { + m_bStop = true; + } + #if !defined(ANDROID_NDK) delete m_InputThread; m_InputThread = NULL; #endif @@ -222,7 +239,7 @@ void cRoot::Start(void) delete m_FurnaceRecipe; m_FurnaceRecipe = NULL; delete m_CraftingRecipes; m_CraftingRecipes = NULL; LOGD("Forgetting groups..."); - delete m_GroupManager; m_GroupManager = 0; + delete m_GroupManager; m_GroupManager = NULL; LOGD("Unloading worlds..."); UnloadWorlds(); @@ -233,12 +250,11 @@ void cRoot::Start(void) cBlockHandler::Deinit(); LOG("Cleaning up..."); - //delete HeartBeat; HeartBeat = 0; - delete m_Server; m_Server = 0; + delete m_Server; m_Server = NULL; LOG("Shutdown successful!"); } - delete m_Log; m_Log = 0; + delete m_Log; m_Log = NULL; } diff --git a/src/main.cpp b/src/main.cpp index 1f6aad24f..84339b8d6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,6 +11,10 @@ #include #endif // _MSC_VER +// Here, we have some ALL CAPS variables, to give the impression that this is deeeep, gritty programming :P +bool g_TERMINATE_EVENT_RAISED = false; // If something has told the server to stop; checked periodically in cRoot +bool g_SERVER_TERMINATED = false; // Set to true when the server terminates, so our CTRL handler can then tell Windows to close the console + @@ -33,14 +37,21 @@ - -void ShowCrashReport(int) +void NonCtrlHandler(int a_Signal) { - std::signal(SIGSEGV, SIG_DFL); + LOGD("Terminate event raised from std::signal"); + g_TERMINATE_EVENT_RAISED = true; - printf("\n\nMCServer has crashed!\n"); - - exit(-1); + switch (a_Signal) + { + case SIGSEGV: + { + std::signal(SIGSEGV, SIG_DFL); + LOGWARN("Segmentation fault; MCServer has crashed :("); + exit(EXIT_FAILURE); + } + default: break; + } } @@ -111,13 +122,33 @@ LONG WINAPI LastChanceExceptionFilter(__in struct _EXCEPTION_POINTERS * a_Except +#ifdef _WIN32 +// Handle CTRL events in windows, including console window close +BOOL CtrlHandler(DWORD fdwCtrlType) +{ + g_TERMINATE_EVENT_RAISED = true; + LOGD("Terminate event raised from the Windows CtrlHandler"); + + if (fdwCtrlType == CTRL_CLOSE_EVENT) + { + while (!g_SERVER_TERMINATED) { cSleep::MilliSleep(100); } // Delay as much as possible to try to get the server to shut down cleanly + } + + return TRUE; +} +#endif + + + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // main: int main( int argc, char **argv ) { - (void)argc; - (void)argv; + UNUSED(argc); + UNUSED(argv); #if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER) InitLeakFinder(); @@ -149,6 +180,13 @@ int main( int argc, char **argv ) } #endif // _WIN32 && !_WIN64 // End of dump-file magic + + #ifdef _WIN32 + if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE)) + { + LOGERROR("Could not install the Windows CTRL handler!"); + } + #endif #if defined(_DEBUG) && defined(_MSC_VER) _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); @@ -160,7 +198,9 @@ int main( int argc, char **argv ) #endif // _DEBUG && _MSC_VER #ifndef _DEBUG - std::signal(SIGSEGV, ShowCrashReport); + std::signal(SIGSEGV, NonCtrlHandler); + std::signal(SIGTERM, NonCtrlHandler); + std::signal(SIGINT, NonCtrlHandler); #endif // DEBUG: test the dumpfile creation: @@ -188,8 +228,10 @@ int main( int argc, char **argv ) #if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER) DeinitLeakFinder(); #endif - - return 0; + + g_SERVER_TERMINATED = true; + + return EXIT_SUCCESS; } From b02a81678c22b00955bc3b2b87ceed55027bb35a Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 22 Dec 2013 20:04:17 +0000 Subject: [PATCH 05/19] Implemented knockback and critical hit --- src/Entities/Entity.cpp | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 8fcdcc82f..0f5ed7262 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -13,6 +13,7 @@ #include "../Bindings/PluginManager.h" #include "../Tracer.h" #include "Minecart.h" +#include "Player.h" @@ -239,10 +240,14 @@ void cEntity::TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_R TDI.Attacker = a_Attacker; TDI.RawDamage = a_RawDamage; TDI.FinalDamage = a_FinalDamage; - Vector3d Heading; - Heading.x = sin(GetRotation()); - Heading.y = 0.4; // TODO: adjust the amount of "up" knockback when testing - Heading.z = cos(GetRotation()); + + Vector3d Heading(0, 0, 0); + if (a_Attacker != NULL) + { + Heading = a_Attacker->GetLookVector() * (a_Attacker->IsSprinting() ? 10 : 8); + } + Heading.y += 3; + TDI.Knockback = Heading * a_KnockbackAmount; DoTakeDamage(TDI); } @@ -297,6 +302,16 @@ void cEntity::DoTakeDamage(TakeDamageInfo & a_TDI) return; } + if ((a_TDI.Attacker != NULL) && (a_TDI.Attacker->IsPlayer())) + { + // IsOnGround() only is true if the player is moving downwards + if (!((cPlayer *)a_TDI.Attacker)->IsOnGround()) // TODO: Better damage increase, and check for enchantments (and use magic critical instead of plain) + { + a_TDI.FinalDamage + 2; + m_World->BroadcastEntityAnimation(*this, 4); // Critical hit + } + } + m_Health -= (short)a_TDI.FinalDamage; // TODO: Apply damage to armor @@ -306,6 +321,8 @@ void cEntity::DoTakeDamage(TakeDamageInfo & a_TDI) m_Health = 0; } + AddSpeed(a_TDI.Knockback * 3); + m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_HURT); if (m_Health <= 0) From 48b388aa97fa5e3819f91ab6a77dfdc4af5b1a0a Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 22 Dec 2013 20:06:15 +0000 Subject: [PATCH 06/19] A fix for daylight sensors --- src/Simulator/RedstoneSimulator.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp index 10b750aeb..c26663aa1 100644 --- a/src/Simulator/RedstoneSimulator.cpp +++ b/src/Simulator/RedstoneSimulator.cpp @@ -899,7 +899,7 @@ void cRedstoneSimulator::HandleNoteBlock(int a_BlockX, int a_BlockY, int a_Block void cRedstoneSimulator::HandleDaylightSensor(int a_BlockX, int a_BlockY, int a_BlockZ) { - for (int Y = a_BlockY + 1; Y < 10; Y++) + for (int Y = a_BlockY + 1; Y < cChunkDef::Height; Y++) { if (!g_BlockTransparent[m_World.GetBlock(a_BlockX, Y, a_BlockZ)]) { @@ -907,7 +907,8 @@ void cRedstoneSimulator::HandleDaylightSensor(int a_BlockX, int a_BlockY, int a_ } } - if (m_World.GetSkyDarkness() < 8) + NIBBLETYPE SkyLight = m_World.GetBlockSkyLight(a_BlockX, a_BlockY + 1, a_BlockZ) - m_World.GetSkyDarkness(); + if (SkyLight > 8) { SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_DAYLIGHT_SENSOR); } From 11fbfb458d3da8dcba4fdc2d65783a90b660e62d Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 22 Dec 2013 23:20:43 +0000 Subject: [PATCH 07/19] Daylight sensor sensing enhancement --- src/Simulator/RedstoneSimulator.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp index c26663aa1..3e267525f 100644 --- a/src/Simulator/RedstoneSimulator.cpp +++ b/src/Simulator/RedstoneSimulator.cpp @@ -899,18 +899,20 @@ void cRedstoneSimulator::HandleNoteBlock(int a_BlockX, int a_BlockY, int a_Block void cRedstoneSimulator::HandleDaylightSensor(int a_BlockX, int a_BlockY, int a_BlockZ) { - for (int Y = a_BlockY + 1; Y < cChunkDef::Height; Y++) - { - if (!g_BlockTransparent[m_World.GetBlock(a_BlockX, Y, a_BlockZ)]) - { - return; - } - } + int a_ChunkX, a_ChunkZ; + cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, a_ChunkX, a_ChunkZ); - NIBBLETYPE SkyLight = m_World.GetBlockSkyLight(a_BlockX, a_BlockY + 1, a_BlockZ) - m_World.GetSkyDarkness(); - if (SkyLight > 8) + if (!m_World.IsChunkLighted(a_ChunkX, a_ChunkZ)) { - SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_DAYLIGHT_SENSOR); + m_World.QueueLightChunk(a_ChunkX, a_ChunkZ); + } + else + { + NIBBLETYPE SkyLight = m_World.GetBlockSkyLight(a_BlockX, a_BlockY + 1, a_BlockZ) - m_World.GetSkyDarkness(); + if (SkyLight > 8) + { + SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_DAYLIGHT_SENSOR); + } } } From 003043f8abcda9c3117a4824d21bbaf45bc5b72a Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Mon, 23 Dec 2013 09:41:34 +0000 Subject: [PATCH 08/19] Added some comments in main.cpp --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 84339b8d6..a4ee09952 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -129,7 +129,7 @@ BOOL CtrlHandler(DWORD fdwCtrlType) g_TERMINATE_EVENT_RAISED = true; LOGD("Terminate event raised from the Windows CtrlHandler"); - if (fdwCtrlType == CTRL_CLOSE_EVENT) + if (fdwCtrlType == CTRL_CLOSE_EVENT) // Console windows closed via 'x' button, Windows will try to close immediately, therefore... { while (!g_SERVER_TERMINATED) { cSleep::MilliSleep(100); } // Delay as much as possible to try to get the server to shut down cleanly } From d8221854d2f529e8165d5153c767bb29a54646a8 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Mon, 23 Dec 2013 09:41:45 +0000 Subject: [PATCH 09/19] Fixed a comment in Entity.cpp --- src/Entities/Entity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 0f5ed7262..d82a89ab2 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -304,7 +304,7 @@ void cEntity::DoTakeDamage(TakeDamageInfo & a_TDI) if ((a_TDI.Attacker != NULL) && (a_TDI.Attacker->IsPlayer())) { - // IsOnGround() only is true if the player is moving downwards + // IsOnGround() only is false if the player is moving downwards if (!((cPlayer *)a_TDI.Attacker)->IsOnGround()) // TODO: Better damage increase, and check for enchantments (and use magic critical instead of plain) { a_TDI.FinalDamage + 2; From 9c796bf6b42b54ce5efe294c03ffd28366917805 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Mon, 23 Dec 2013 09:51:41 +0000 Subject: [PATCH 10/19] Clarified some code in Player.cpp --- src/Entities/Player.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index aedd3b77e..0c133d3fa 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -987,8 +987,11 @@ void cPlayer::SetGameMode(eGameMode a_GameMode) m_GameMode = a_GameMode; m_ClientHandle->SendGameMode(a_GameMode); - SetFlying(false); - SetCanFly(false); + if (a_GameMode != gmCreative) + { + SetFlying(false); + SetCanFly(false); + } } From 76444470a482a9d05c7c3eb95d0f9ac118dda53e Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Mon, 23 Dec 2013 15:22:05 +0000 Subject: [PATCH 11/19] Provides an enhancement to daylight sensors --- src/Simulator/RedstoneSimulator.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp index 3e267525f..638b977d4 100644 --- a/src/Simulator/RedstoneSimulator.cpp +++ b/src/Simulator/RedstoneSimulator.cpp @@ -112,10 +112,35 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c LOGD("cRedstoneSimulator: Erased block %s from powered blocks list due to present/past metadata mismatch", ItemToFullString(itr->a_SourceBlock).c_str()); itr = m_PoweredBlocks.erase(itr); } + else if (SourceBlockType == E_BLOCK_DAYLIGHT_SENSOR) + { + if (!a_Chunk->IsLightValid()) + { + m_World.QueueLightChunk(a_ChunkX, a_ChunkZ); + itr++; + continue; + } + else + { + NIBBLETYPE SkyLight; + a_Chunk->UnboundedRelGetBlockSkyLight(RelX, itr->a_SourcePos.y + 1, RelZ, SkyLight); + + if (a_Chunk->GetTimeAlteredLight(SkyLight) <= 8) // Could use SkyLight - m_World.GetSkyDarkness(); + { + LOGD("cRedstoneSimulator: Erased daylight sensor from powered blocks list due to insufficient light level"); + itr = m_PoweredBlocks.erase(itr); + } + else + { + itr++; + continue; + } + } + } else if ((SourceBlockType == E_BLOCK_REDSTONE_WIRE) && (DestBlockType == E_BLOCK_REDSTONE_WIRE)) { // It is simply not allowed that a wire powers another wire, presuming that data here is sane and a dest and source are beside each other - LOGD("cRedstoneSimulator: Erased redstone wire from powered blocks list because it's source was also wire"); + LOGD("cRedstoneSimulator: Erased redstone wire from powered blocks list because its source was also wire"); itr = m_PoweredBlocks.erase(itr); } else @@ -283,7 +308,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c } } - ++dataitr; + dataitr++; } } From 1014c737a4f16ce374fa834822ba173c00cae678 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Mon, 23 Dec 2013 21:18:01 +0000 Subject: [PATCH 12/19] Improved player fall particle positions --- src/Entities/Player.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 0c133d3fa..26572f39b 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -457,11 +457,8 @@ void cPlayer::SetTouchGround(bool a_bTouchGround) TakeDamage(dtFalling, NULL, Damage, Damage, 0); } - GetWorld()->BroadcastSoundParticleEffect( - 2006, - (int)GetPosX(), (int)GetPosY() - 1, (int)GetPosZ(), - Damage // Used as particle effect speed modifier - ); + // Apparently, Mojang changed player positions to always be rounded up. Normally, it doesn't affect much, but we need effect positions to be precise, so ceil() + GetWorld()->BroadcastSoundParticleEffect(2006, (int)floor(GetPosX()), (int)GetPosY() - 1, (int)floor(GetPosZ()), Damage /* Used as particle effect speed modifier */); } m_LastGroundHeight = (float)GetPosY(); From 89f87f66a5b64619cacf86461c1a0f26563e34c5 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 24 Dec 2013 15:02:35 +0000 Subject: [PATCH 13/19] Improved knockback animation * Critical hits now actually increase damage * Looking down at an entity and hitting them still produces upwards motion (as per Vanilla experience) * Reduced force to be more realistic --- src/Entities/Entity.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index d82a89ab2..8a74c9da4 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -246,7 +246,7 @@ void cEntity::TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_R { Heading = a_Attacker->GetLookVector() * (a_Attacker->IsSprinting() ? 10 : 8); } - Heading.y += 3; + Heading.y = 2; TDI.Knockback = Heading * a_KnockbackAmount; DoTakeDamage(TDI); @@ -307,7 +307,7 @@ void cEntity::DoTakeDamage(TakeDamageInfo & a_TDI) // IsOnGround() only is false if the player is moving downwards if (!((cPlayer *)a_TDI.Attacker)->IsOnGround()) // TODO: Better damage increase, and check for enchantments (and use magic critical instead of plain) { - a_TDI.FinalDamage + 2; + a_TDI.FinalDamage += 2; m_World->BroadcastEntityAnimation(*this, 4); // Critical hit } } @@ -321,7 +321,7 @@ void cEntity::DoTakeDamage(TakeDamageInfo & a_TDI) m_Health = 0; } - AddSpeed(a_TDI.Knockback * 3); + AddSpeed(a_TDI.Knockback * 2); m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_HURT); From c6314e89357434d49fc185e94bccb0fe4b1bc3d7 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 24 Dec 2013 15:02:55 +0000 Subject: [PATCH 14/19] Implemented stone and wooden pressure plates --- src/Simulator/RedstoneSimulator.cpp | 102 +++++++++++++++++++++++++++- src/Simulator/RedstoneSimulator.h | 6 +- 2 files changed, 105 insertions(+), 3 deletions(-) diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp index 638b977d4..b78e6582d 100644 --- a/src/Simulator/RedstoneSimulator.cpp +++ b/src/Simulator/RedstoneSimulator.cpp @@ -8,6 +8,7 @@ #include "../Blocks/BlockTorch.h" #include "../Blocks/BlockDoor.h" #include "../Piston.h" +#include "../Tracer.h" @@ -106,7 +107,8 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c ((SourceBlockType == E_BLOCK_REDSTONE_WIRE) && (SourceBlockMeta == 0)) || ((SourceBlockType == E_BLOCK_LEVER) && !IsLeverOn(SourceBlockMeta)) || ((SourceBlockType == E_BLOCK_DETECTOR_RAIL) && (SourceBlockMeta & 0x08) == 0x08) || - (((SourceBlockType == E_BLOCK_STONE_BUTTON) || (SourceBlockType == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(SourceBlockMeta))) + (((SourceBlockType == E_BLOCK_STONE_BUTTON) || (SourceBlockType == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(SourceBlockMeta))) || + (((SourceBlockType == E_BLOCK_STONE_PRESSURE_PLATE) || (SourceBlockType == E_BLOCK_WOODEN_PRESSURE_PLATE)) && (SourceBlockMeta == 0)) ) { LOGD("cRedstoneSimulator: Erased block %s from powered blocks list due to present/past metadata mismatch", ItemToFullString(itr->a_SourceBlock).c_str()); @@ -306,6 +308,12 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c HandleRail(a_X, dataitr->y, a_Z, BlockType); break; } + case E_BLOCK_WOODEN_PRESSURE_PLATE: + case E_BLOCK_STONE_PRESSURE_PLATE: + { + HandlePressurePlate(a_X, dataitr->y, a_Z, BlockType); + break; + } } dataitr++; @@ -945,6 +953,98 @@ void cRedstoneSimulator::HandleDaylightSensor(int a_BlockX, int a_BlockY, int a_ +void cRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType) +{ + switch (a_MyType) + { + case E_BLOCK_STONE_PRESSURE_PLATE: + { + // MCS feature - stone pressure plates can only be triggered by players :D + cPlayer * a_Player = m_World.FindClosestPlayer(Vector3f(a_BlockX + 0.5f, (float)a_BlockY, a_BlockZ + 0.5f), 0.5f); + + if (a_Player != NULL) + { + m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x1); + SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_STONE_PRESSURE_PLATE); + } + else + { + m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x0); + } + break; + } + case E_BLOCK_WOODEN_PRESSURE_PLATE: + { + class cWoodenPressurePlateCallback : + public cEntityCallback + { + public: + cWoodenPressurePlateCallback(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) : + m_X(a_BlockX), + m_Y(a_BlockY), + m_Z(a_BlockZ), + m_World(a_World), + m_Entity(NULL) + { + } + + virtual bool Item(cEntity * a_Entity) override + { + cTracer LineOfSight(m_World); + + Vector3f EntityPos = a_Entity->GetPosition(); + Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f); + float Distance = (EntityPos - BlockPos).Length(); + + if (Distance < 0.5) + { + if (!LineOfSight.Trace(BlockPos, (EntityPos - BlockPos), (int)(EntityPos - BlockPos).Length())) + { + m_Entity = a_Entity; + return true; // Break out, we only need to know for wooden plates that at least one entity is on top + } + } + return false; + } + + bool FoundEntity(void) const + { + return m_Entity != NULL; + } + + protected: + cEntity * m_Entity; + cWorld * m_World; + + int m_X; + int m_Y; + int m_Z; + } ; + + cWoodenPressurePlateCallback WoodenPressurePlateCallback(a_BlockX, a_BlockY, a_BlockZ, &m_World); + m_World.ForEachEntity(WoodenPressurePlateCallback); + + if (WoodenPressurePlateCallback.FoundEntity()) + { + m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x1); + SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_WOODEN_PRESSURE_PLATE); + } + else + { + m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x0); + } + break; + } + default: + LOGD("Unimplemented pressure plate type %s in cRedstoneSimulator", ItemToFullString(a_MyType).c_str()); + break; + } +} + + + + + bool cRedstoneSimulator::AreCoordsDirectlyPowered(int a_BlockX, int a_BlockY, int a_BlockZ) { for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr) // Check powered list diff --git a/src/Simulator/RedstoneSimulator.h b/src/Simulator/RedstoneSimulator.h index 309135497..60c86a3c5 100644 --- a/src/Simulator/RedstoneSimulator.h +++ b/src/Simulator/RedstoneSimulator.h @@ -89,6 +89,10 @@ private: void HandleRedstoneLever(int a_BlockX, int a_BlockY, int a_BlockZ); /// Handles buttons void HandleRedstoneButton(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType); + /// Handles daylight sensors + void HandleDaylightSensor(int a_BlockX, int a_BlockY, int a_BlockZ); + /// Handles pressure plates + void HandlePressurePlate(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType); /* ==================== */ /* ====== CARRIERS ====== */ @@ -115,8 +119,6 @@ private: void HandleTrapdoor(int a_BlockX, int a_BlockY, int a_BlockZ); /// Handles noteblocks void HandleNoteBlock(int a_BlockX, int a_BlockY, int a_BlockZ); - /// Handles noteblocks - void HandleDaylightSensor(int a_BlockX, int a_BlockY, int a_BlockZ); /* ===================== */ /* ====== Helper functions ====== */ From ae6cb01e5666a8d4cedaf221f2e784f862784482 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 24 Dec 2013 15:16:30 +0000 Subject: [PATCH 15/19] Fixed comments in main.cpp and Player.cpp --- src/Entities/Player.cpp | 2 +- src/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 26572f39b..6d199e130 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -457,7 +457,7 @@ void cPlayer::SetTouchGround(bool a_bTouchGround) TakeDamage(dtFalling, NULL, Damage, Damage, 0); } - // Apparently, Mojang changed player positions to always be rounded up. Normally, it doesn't affect much, but we need effect positions to be precise, so ceil() + // Mojang uses floor() to get X and Z positions, instead of just casting it to an (int) GetWorld()->BroadcastSoundParticleEffect(2006, (int)floor(GetPosX()), (int)GetPosY() - 1, (int)floor(GetPosZ()), Damage /* Used as particle effect speed modifier */); } diff --git a/src/main.cpp b/src/main.cpp index a4ee09952..81c6b41e4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -129,7 +129,7 @@ BOOL CtrlHandler(DWORD fdwCtrlType) g_TERMINATE_EVENT_RAISED = true; LOGD("Terminate event raised from the Windows CtrlHandler"); - if (fdwCtrlType == CTRL_CLOSE_EVENT) // Console windows closed via 'x' button, Windows will try to close immediately, therefore... + if (fdwCtrlType == CTRL_CLOSE_EVENT) // Console window closed via 'x' button, Windows will try to close immediately, therefore... { while (!g_SERVER_TERMINATED) { cSleep::MilliSleep(100); } // Delay as much as possible to try to get the server to shut down cleanly } From 508e505aced6f80a0ed1f3d89495add658b11956 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Tue, 24 Dec 2013 23:47:04 +0000 Subject: [PATCH 16/19] Used IsGamemodeCreative() function --- src/Entities/Player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 6d199e130..a4b580b00 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -984,7 +984,7 @@ void cPlayer::SetGameMode(eGameMode a_GameMode) m_GameMode = a_GameMode; m_ClientHandle->SendGameMode(a_GameMode); - if (a_GameMode != gmCreative) + if (!IsGameModeCreative()) { SetFlying(false); SetCanFly(false); From 40c2826a21d71dd8829a29f97fdfb36b68eaba14 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 25 Dec 2013 14:05:37 +0000 Subject: [PATCH 17/19] Braced up some code --- src/Entities/Player.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index a4b580b00..41c1542d3 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -249,7 +249,9 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) } if (IsFlying()) + { m_LastGroundHeight = (float)GetPosY(); + } } From 1a02d94ed2ff0b7d948319c48905408dde9f9b35 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 25 Dec 2013 14:12:48 +0000 Subject: [PATCH 18/19] Fixed rails not updating with diagonals --- src/Blocks/BlockRail.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/Blocks/BlockRail.h b/src/Blocks/BlockRail.h index 24a101652..55cadfa48 100644 --- a/src/Blocks/BlockRail.h +++ b/src/Blocks/BlockRail.h @@ -43,6 +43,40 @@ public: } + virtual void OnPlaced(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override + { + super::OnPlaced(a_World, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); + + // Alert diagonal rails + OnNeighborChanged(a_World, a_BlockX + 1, a_BlockY + 1, a_BlockZ); + OnNeighborChanged(a_World, a_BlockX - 1, a_BlockY + 1, a_BlockZ); + OnNeighborChanged(a_World, a_BlockX, a_BlockY + 1, a_BlockZ + 1); + OnNeighborChanged(a_World, a_BlockX, a_BlockY + 1, a_BlockZ - 1); + + OnNeighborChanged(a_World, a_BlockX + 1, a_BlockY - 1, a_BlockZ); + OnNeighborChanged(a_World, a_BlockX - 1, a_BlockY - 1, a_BlockZ); + OnNeighborChanged(a_World, a_BlockX, a_BlockY - 1, a_BlockZ + 1); + OnNeighborChanged(a_World, a_BlockX, a_BlockY - 1, a_BlockZ - 1); + } + + + virtual void OnDestroyed(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override + { + super::OnDestroyed(a_World, a_BlockX, a_BlockY, a_BlockZ); + + // Alert diagonal rails + OnNeighborChanged(a_World, a_BlockX + 1, a_BlockY + 1, a_BlockZ); + OnNeighborChanged(a_World, a_BlockX - 1, a_BlockY + 1, a_BlockZ); + OnNeighborChanged(a_World, a_BlockX, a_BlockY + 1, a_BlockZ + 1); + OnNeighborChanged(a_World, a_BlockX, a_BlockY + 1, a_BlockZ - 1); + + OnNeighborChanged(a_World, a_BlockX + 1, a_BlockY - 1, a_BlockZ); + OnNeighborChanged(a_World, a_BlockX - 1, a_BlockY - 1, a_BlockZ); + OnNeighborChanged(a_World, a_BlockX, a_BlockY - 1, a_BlockZ + 1); + OnNeighborChanged(a_World, a_BlockX, a_BlockY - 1, a_BlockZ - 1); + } + + virtual void OnNeighborChanged(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override { NIBBLETYPE Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); From d0572e73a06a4f2a6f461a4a1d0b0ae3ff74af3d Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Thu, 26 Dec 2013 00:12:06 +0000 Subject: [PATCH 19/19] Moved increment operator to back of variables --- src/Simulator/RedstoneSimulator.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp index b78e6582d..f65908729 100644 --- a/src/Simulator/RedstoneSimulator.cpp +++ b/src/Simulator/RedstoneSimulator.cpp @@ -119,7 +119,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c if (!a_Chunk->IsLightValid()) { m_World.QueueLightChunk(a_ChunkX, a_ChunkZ); - itr++; + ++itr; continue; } else @@ -134,7 +134,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c } else { - itr++; + ++itr; continue; } } @@ -147,7 +147,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c } else { - itr++; + ++itr; } } @@ -192,7 +192,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c } else { - itr++; + ++itr; } } @@ -213,7 +213,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c } else { - itr++; + ++itr; } } @@ -234,7 +234,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c continue; } - itr++; + ++itr; } for (cRedstoneSimulatorChunkData::iterator dataitr = ChunkData.begin(), end = ChunkData.end(); dataitr != end;) @@ -316,7 +316,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c } } - dataitr++; + ++dataitr; } } @@ -630,7 +630,7 @@ void cRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_BlockY, int QueueRepeaterPowerChange(a_BlockX, a_BlockY, a_BlockZ, a_Meta, 0, false); } - for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); itr++) + for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); ++itr) { if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { @@ -1446,7 +1446,7 @@ void cRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_BlockX, int a void cRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, short a_ElapsedTicks, bool ShouldPowerOn) { - for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); itr++) + for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); ++itr) { if (itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) {