From 95be80cdb5322720e7c9fbd13ec2692288afd931 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sat, 14 Dec 2013 16:52:22 +0000 Subject: [PATCH] Implemented note block playing and fixed wire Game of Thrones music in Minecraft, here I come! --- src/Bindings/ManualBindings.cpp | 2 ++ src/Chunk.cpp | 32 ++++++++++++++++++ src/Chunk.h | 6 +++- src/ChunkMap.cpp | 17 ++++++++++ src/ChunkMap.h | 5 +++ src/Simulator/RedstoneSimulator.cpp | 52 ++++++++++++++++++++++++++--- src/Simulator/RedstoneSimulator.h | 2 ++ src/World.cpp | 9 +++++ src/World.h | 5 +++ 9 files changed, 125 insertions(+), 5 deletions(-) diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index 4f7e1470a..2e19c2581 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -18,6 +18,7 @@ #include "../BlockEntities/DropperEntity.h" #include "../BlockEntities/FurnaceEntity.h" #include "../BlockEntities/HopperEntity.h" +#include "../BlockEntities/NoteEntity.h" #include "md5/md5.h" #include "../LineBlockTracer.h" @@ -2217,6 +2218,7 @@ void ManualBindings::Bind(lua_State * tolua_S) tolua_function(tolua_S, "DoWithDropperAt", tolua_DoWithXYZ); tolua_function(tolua_S, "DoWithEntityByID", tolua_DoWithID< cWorld, cEntity, &cWorld::DoWithEntityByID>); tolua_function(tolua_S, "DoWithFurnaceAt", tolua_DoWithXYZ); + tolua_function(tolua_S, "DoWithNoteBlockAt", tolua_DoWithXYZ); tolua_function(tolua_S, "DoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::DoWithPlayer>); tolua_function(tolua_S, "FindAndDoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::FindAndDoWithPlayer>); tolua_function(tolua_S, "ForEachBlockEntityInChunk", tolua_ForEachInChunk); diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 42969bf6d..b3c1896dc 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -2225,6 +2225,38 @@ bool cChunk::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceC +bool cChunk::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback) +{ + // The blockentity list is locked by the parent chunkmap's CS + for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2) + { + ++itr2; + if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ)) + { + continue; + } + if ((*itr)->GetBlockType() != E_BLOCK_NOTE_BLOCK) + { + // There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out + return false; + } + + // The correct block entity is here, + if (a_Callback.Item((cNoteEntity *)*itr)) + { + return false; + } + return true; + } // for itr - m_BlockEntitites[] + + // Not found: + return false; +} + + + + + bool cChunk::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4) { // The blockentity list is locked by the parent chunkmap's CS diff --git a/src/Chunk.h b/src/Chunk.h index 9e5d117c5..a5bc9863b 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -35,7 +35,6 @@ namespace Json class cWorld; -class cFurnaceEntity; class cClientHandle; class cServer; class MTRand; @@ -44,6 +43,7 @@ class cChunkMap; class cChestEntity; class cDispenserEntity; class cFurnaceEntity; +class cNoteEntity; class cBlockArea; class cPawn; class cPickup; @@ -58,6 +58,7 @@ typedef cItemCallback cEntityCallback; typedef cItemCallback cChestCallback; typedef cItemCallback cDispenserCallback; typedef cItemCallback cFurnaceCallback; +typedef cItemCallback cNoteBlockCallback; @@ -246,6 +247,9 @@ public: /// Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback & a_Callback); // Lua-accessible + /// Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found + bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback); + /// Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp index cb722af3b..f2195741d 100644 --- a/src/ChunkMap.cpp +++ b/src/ChunkMap.cpp @@ -1899,6 +1899,23 @@ bool cChunkMap::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurna +bool cChunkMap::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback) +{ + int ChunkX, ChunkZ; + int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ; + cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ); + cCSLock Lock(m_CSLayers); + cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ); + if ((Chunk == NULL) && !Chunk->IsValid()) + { + return false; + } + return Chunk->DoWithNoteBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); +} + + + + bool cChunkMap::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4) { diff --git a/src/ChunkMap.h b/src/ChunkMap.h index ef070194b..f079c9a1b 100644 --- a/src/ChunkMap.h +++ b/src/ChunkMap.h @@ -22,6 +22,7 @@ class cDispenserEntity; class cDropperEntity; class cDropSpenserEntity; class cFurnaceEntity; +class cNoteEntity; class cPawn; class cPickup; class cChunkDataSerializer; @@ -38,6 +39,7 @@ typedef cItemCallback cDispenserCallback; typedef cItemCallback cDropperCallback; typedef cItemCallback cDropSpenserCallback; typedef cItemCallback cFurnaceCallback; +typedef cItemCallback cNoteBlockCallback; typedef cItemCallback cChunkCallback; @@ -228,6 +230,9 @@ public: /// Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback & a_Callback); // Lua-accessible + /// Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found + bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback); // Lua-accessible + /// Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp index f61e1c63b..e1ffaf30f 100644 --- a/src/Simulator/RedstoneSimulator.cpp +++ b/src/Simulator/RedstoneSimulator.cpp @@ -3,6 +3,7 @@ #include "RedstoneSimulator.h" #include "../BlockEntities/DropSpenserEntity.h" +#include "../BlockEntities/NoteEntity.h" #include "../Entities/TNTEntity.h" #include "../Blocks/BlockTorch.h" #include "../Blocks/BlockDoor.h" @@ -196,6 +197,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c case E_BLOCK_TNT: HandleTNT(a_X, dataitr->y, a_Z); break; case E_BLOCK_TRAPDOOR: HandleTrapdoor(a_X, dataitr->y, a_Z); break; case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(a_X, dataitr->y, a_Z); break; + case E_BLOCK_NOTE_BLOCK: HandleNoteBlock(a_X, dataitr->y, a_Z); break; case E_BLOCK_REDSTONE_TORCH_OFF: case E_BLOCK_REDSTONE_TORCH_ON: @@ -459,12 +461,12 @@ void cRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_Bl } } - // Wire still powered, power blocks beneath - SetBlockPowered(a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE); - SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_YM, E_BLOCK_REDSTONE_WIRE); - if (m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) != 0) // A powered wire { + // Wire still powered, power blocks beneath + SetBlockPowered(a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE); + SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_YM, E_BLOCK_REDSTONE_WIRE); + switch (GetWireDirection(a_BlockX, a_BlockY, a_BlockZ)) { case REDSTONE_NONE: @@ -821,6 +823,48 @@ void cRedstoneSimulator::HandleTrapdoor(int a_BlockX, int a_BlockY, int a_BlockZ +void cRedstoneSimulator::HandleNoteBlock(int a_BlockX, int a_BlockY, int a_BlockZ) +{ + bool m_bAreCoordsPowered = AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ); + + if (m_bAreCoordsPowered) + { + if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, true)) + { + class cSetPowerToNoteBlock : + public cNoteBlockCallback + { + bool m_IsPowered; + public: + cSetPowerToNoteBlock(bool a_IsPowered) : m_IsPowered(a_IsPowered) {} + + virtual bool Item(cNoteEntity * a_NoteBlock) override + { + if (m_IsPowered) + { + a_NoteBlock->MakeSound(); + } + return false; + } + } NoteBlockSP(m_bAreCoordsPowered); + + m_World.DoWithNoteBlockAt(a_BlockX, a_BlockY, a_BlockZ, NoteBlockSP); + SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, true); + } + } + else + { + if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, false)) + { + SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, false); + } + } +} + + + + + 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 23ac510fc..9bdeb8f32 100644 --- a/src/Simulator/RedstoneSimulator.h +++ b/src/Simulator/RedstoneSimulator.h @@ -112,6 +112,8 @@ private: void HandleRail(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType); /// Handles trapdoors void HandleTrapdoor(int a_BlockX, int a_BlockY, int a_BlockZ); + /// Handles noteblocks + void HandleNoteBlock(int a_BlockX, int a_BlockY, int a_BlockZ); /* ===================== */ /* ====== Helper functions ====== */ diff --git a/src/World.cpp b/src/World.cpp index 564905d33..9ec389be9 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1129,6 +1129,15 @@ bool cWorld::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceC +bool cWorld::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback) +{ + return m_ChunkMap->DoWithNoteBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); +} + + + + + bool cWorld::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4) { return m_ChunkMap->GetSignLines(a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4); diff --git a/src/World.h b/src/World.h index fc821a68a..5cd8b41b6 100644 --- a/src/World.h +++ b/src/World.h @@ -42,6 +42,7 @@ class cChunkGenerator; // The thread responsible for generating chunks class cChestEntity; class cDispenserEntity; class cFurnaceEntity; +class cNoteEntity; class cMobCensus; typedef std::list< cPlayer * > cPlayerList; @@ -51,6 +52,7 @@ typedef cItemCallback cEntityCallback; typedef cItemCallback cChestCallback; typedef cItemCallback cDispenserCallback; typedef cItemCallback cFurnaceCallback; +typedef cItemCallback cNoteBlockCallback; @@ -444,6 +446,9 @@ public: /// Calls the callback for the furnace at the specified coords; returns false if there's no furnace at those coords or callback returns true, returns true if found bool DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback & a_Callback); // Exported in ManualBindings.cpp + + /// Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found + bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback); // Exported in ManualBindings.cpp /// Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Exported in ManualBindings.cpp