From 1aebcea095e92572a39cb6555cba8517234b156c Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Wed, 15 Feb 2012 14:22:44 +0000 Subject: [PATCH] Restored chest and furnace functionality as it was (it's basically working but joined chests show single-chest window) git-svn-id: http://mc-server.googlecode.com/svn/trunk@263 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/cBlockEntity.h | 2 +- source/cChestEntity.cpp | 10 +-- source/cChestEntity.h | 4 +- source/cChunk.cpp | 13 +++ source/cChunk.h | 2 + source/cChunkMap.cpp | 38 +++++++++ source/cChunkMap.h | 35 +++++++- source/cClientHandle.cpp | 172 +++++++++++++++++++------------------- source/cFurnaceEntity.cpp | 8 +- source/cFurnaceEntity.h | 3 +- source/cSignEntity.cpp | 2 +- source/cSignEntity.h | 4 +- source/cWorld.h | 5 ++ 13 files changed, 194 insertions(+), 104 deletions(-) diff --git a/source/cBlockEntity.h b/source/cBlockEntity.h index 83a7ebffc..4ac453e6f 100644 --- a/source/cBlockEntity.h +++ b/source/cBlockEntity.h @@ -41,7 +41,7 @@ public: cWorld * GetWorld(void) const {return m_World; } - virtual void UsedBy( cPlayer & a_Player ) = 0; + virtual void UsedBy( cPlayer * a_Player ) = 0; virtual void SendTo( cClientHandle* a_Client ) { (void)a_Client; } protected: diff --git a/source/cChestEntity.cpp b/source/cChestEntity.cpp index e96d4bbb2..c79057829 100644 --- a/source/cChestEntity.cpp +++ b/source/cChestEntity.cpp @@ -184,7 +184,7 @@ void cChestEntity::SendTo( cClientHandle* a_Client, cServer* a_Server ) -void cChestEntity::UsedBy( cPlayer & a_Player ) +void cChestEntity::UsedBy( cPlayer * a_Player ) { LOG("Used a chest"); // m_Content[0].m_ItemCount = 1; @@ -203,10 +203,10 @@ void cChestEntity::UsedBy( cPlayer & a_Player ) } if ( GetWindow() ) { - if( a_Player.GetWindow() != GetWindow() ) + if( a_Player->GetWindow() != GetWindow() ) { - a_Player.OpenWindow( GetWindow() ); - GetWindow()->SendWholeWindow( a_Player.GetClientHandle() ); + a_Player->OpenWindow( GetWindow() ); + GetWindow()->SendWholeWindow( a_Player->GetClientHandle() ); } } cPacket_BlockAction ChestOpen; @@ -215,7 +215,7 @@ void cChestEntity::UsedBy( cPlayer & a_Player ) ChestOpen.m_PosZ = GetPosZ(); ChestOpen.m_Byte1 = (char)1; ChestOpen.m_Byte2 = (char)1; - m_World->GetChunkOfBlock(m_PosX, m_PosY, m_PosZ)->Broadcast(&ChestOpen); + m_World->BroadcastToChunkOfBlock(m_PosX, m_PosY, m_PosZ, &ChestOpen); } diff --git a/source/cChestEntity.h b/source/cChestEntity.h index 6d26d069f..d3d98739b 100644 --- a/source/cChestEntity.h +++ b/source/cChestEntity.h @@ -44,14 +44,14 @@ public: void SendTo( cClientHandle* a_Client, cServer* a_Server ); - virtual void UsedBy( cPlayer & a_Player ); + virtual void UsedBy( cPlayer * a_Player ) override; cChestEntity *GetJoinedChest() { return m_JoinedChest; } void SetJoinedChest(cChestEntity *a_Chest) { m_JoinedChest = a_Chest; } void RemoveJoinedChest(cChestEntity *a_Chest) { if (m_JoinedChest && m_JoinedChest == a_Chest) { m_JoinedChest = NULL; m_TopChest = false; } } int GetChestHeight() { return ((m_JoinedChest) ? c_ChestHeight * 2 : c_ChestHeight); } - cItem *GetContents(bool a_OnlyThis = false); + cItem * GetContents(bool a_OnlyThis = false); static const int c_ChestWidth = 9; static const int c_ChestHeight = 3; diff --git a/source/cChunk.cpp b/source/cChunk.cpp index fec06e947..d1800c053 100644 --- a/source/cChunk.cpp +++ b/source/cChunk.cpp @@ -835,6 +835,19 @@ cBlockEntity * cChunk::GetBlockEntity(int a_X, int a_Y, int a_Z) +void cChunk::UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z) +{ + cBlockEntity * be = GetBlockEntity(a_X, a_Y, a_Z); + if (be != NULL) + { + be->UsedBy(a_Player); + } +} + + + + + void cChunk::CollectPickupsByPlayer(cPlayer * a_Player) { cCSLock Lock(m_CSEntities); diff --git a/source/cChunk.h b/source/cChunk.h index 4ff060b30..0cbc11117 100644 --- a/source/cChunk.h +++ b/source/cChunk.h @@ -85,6 +85,8 @@ public: void AddEntity( cEntity * a_Entity ); void RemoveEntity( cEntity * a_Entity); + + void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z); // [x, y, z] in world block coords inline void RecalculateLighting() { m_bCalculateLighting = true; } // Recalculate lighting next tick inline void RecalculateHeightmap() { m_bCalculateHeightmap = true; } // Recalculate heightmap next tick diff --git a/source/cChunkMap.cpp b/source/cChunkMap.cpp index b864b9792..efb69aca0 100644 --- a/source/cChunkMap.cpp +++ b/source/cChunkMap.cpp @@ -136,6 +136,44 @@ cChunkPtr cChunkMap::GetChunkNoGen( int a_ChunkX, int a_ChunkY, int a_ChunkZ ) +void cChunkMap::BroadcastToChunkOfBlock(int a_X, int a_Y, int a_Z, cPacket * a_Packet, cClientHandle * a_Exclude) +{ + // Broadcasts a_Packet to all clients in the chunk where block [x, y, z] is, except to client a_Exclude + + cCSLock Lock(m_CSLayers); + int ChunkX, ChunkZ; + BlockToChunk(a_X, a_Y, a_Z, ChunkX, ChunkZ); + cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ); + if (Chunk == NULL) + { + return; + } + // Packets can be broadcasted even to invalid chunks! + Chunk->Broadcast(a_Packet); +} + + + + + +void cChunkMap::UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z) +{ + // a_Player rclked block entity at the coords specified, handle it + cCSLock Lock(m_CSLayers); + int ChunkX, ChunkZ; + BlockToChunk(a_X, a_Y, a_Z, ChunkX, ChunkZ); + cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ); + if ((Chunk == NULL) || !Chunk->IsValid()) + { + return; + } + Chunk->UseBlockEntity(a_Player, a_X, a_Y, a_Z); +} + + + + + void cChunkMap::Tick( float a_Dt, MTRand & a_TickRandom ) { cCSLock Lock(m_CSLayers); diff --git a/source/cChunkMap.h b/source/cChunkMap.h index 1d3ddf6aa..bc7bddd96 100644 --- a/source/cChunkMap.h +++ b/source/cChunkMap.h @@ -27,18 +27,51 @@ public: cChunkMap(cWorld* a_World ); ~cChunkMap(); + // TODO: Get rid of these in favor of the direct action methods: cChunkPtr GetChunk ( int a_ChunkX, int a_ChunkY, int a_ChunkZ ); // Also queues the chunk for loading / generating if not valid cChunkPtr GetChunkNoGen( int a_ChunkX, int a_ChunkY, int a_ChunkZ ); // Also queues the chunk for loading if not valid; doesn't generate + + // Direct action methods: + /// Broadcasts a_Packet to all clients in the chunk where block [x, y, z] is, except to client a_Exclude + void BroadcastToChunkOfBlock(int a_X, int a_Y, int a_Z, cPacket * a_Packet, cClientHandle * a_Exclude = NULL); + void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z); // a_Player rclked block entity at the coords specified, handle it void Tick( float a_Dt, MTRand & a_TickRand ); void UnloadUnusedChunks(); void SaveAllChunks(); - cWorld* GetWorld() { return m_World; } + cWorld * GetWorld() { return m_World; } int GetNumChunks(void); + /// Converts absolute block coords into relative (chunk + block) coords: + inline static void AbsoluteToRelative(/* in-out */ int & a_X, int & a_Y, int & a_Z, /* out */ int & a_ChunkX, int & a_ChunkZ ) + { + BlockToChunk(a_X, a_Y, a_Z, a_ChunkX, a_ChunkZ); + + a_X = a_X - a_ChunkX * 16; + a_Z = a_Z - a_ChunkZ*16; + } + + /// Converts absolute block coords to chunk coords: + inline static void BlockToChunk( int a_X, int a_Y, int a_Z, int & a_ChunkX, int & a_ChunkZ ) + { + (void)a_Y; + a_ChunkX = a_X / 16; + if ((a_X < 0) && (a_X % 16 != 0)) + { + a_ChunkX--; + } + a_ChunkZ = a_Z / 16; + if ((a_Z < 0) && (a_Z % 16 != 0)) + { + a_ChunkZ--; + } + } + + + private: class cChunkLayer diff --git a/source/cClientHandle.cpp b/source/cClientHandle.cpp index 92dd93d73..a28d8a56c 100644 --- a/source/cClientHandle.cpp +++ b/source/cClientHandle.cpp @@ -466,9 +466,6 @@ void cClientHandle::HandlePacket(cPacket * a_Packet) { m_TimeLastPacket = cWorld::GetTime(); - // cPacket* CopiedPacket = a_Packet->Clone(); - // a_Packet = CopiedPacket; - // LOG("Recv packet 0x%02x from client \"%s\" (\"%s\")", a_Packet->m_PacketID, m_Socket.GetIPString().c_str(), m_Username.c_str()); if (m_bKicking) @@ -908,41 +905,42 @@ void cClientHandle::HandleBlockPlace(cPacket_BlockPlace * a_Packet) ENUM_BLOCK_ID BlockID = (ENUM_BLOCK_ID)m_Player->GetWorld()->GetBlock(a_Packet->m_PosX, a_Packet->m_PosY, a_Packet->m_PosZ); switch (BlockID) { - case E_BLOCK_REDSTONE_REPEATER_ON: - case E_BLOCK_REDSTONE_REPEATER_OFF: + case E_BLOCK_REDSTONE_REPEATER_ON: + case E_BLOCK_REDSTONE_REPEATER_OFF: { - //no need to update redstone current with a repeater - //todo: Find meta value of repeater and change it to one step more. + // no need to update redstone current with a repeater + // TODO: Find meta value of repeater and change it to one step more. + break; } - break; - case E_BLOCK_WORKBENCH: + + case E_BLOCK_WORKBENCH: { bPlaceBlock = false; cWindow* Window = new cCraftingWindow(0, true); m_Player->OpenWindow(Window); + break; } - break; - case E_BLOCK_FURNACE: - case E_BLOCK_CHEST: + + case E_BLOCK_FURNACE: + case E_BLOCK_CHEST: { bPlaceBlock = false; - cBlockEntity* BlockEntity = m_Player->GetWorld()->GetBlockEntity(a_Packet->m_PosX, a_Packet->m_PosY, a_Packet->m_PosZ); - if (BlockEntity) - { - BlockEntity->UsedBy(*m_Player); - } + m_Player->GetWorld()->UseBlockEntity(m_Player, a_Packet->m_PosX, a_Packet->m_PosY, a_Packet->m_PosZ); + break; } - break; - case E_BLOCK_WOODEN_DOOR: + + case E_BLOCK_WOODEN_DOOR: { bPlaceBlock = false; cDoors::ChangeDoor(m_Player->GetWorld(), a_Packet->m_PosX, a_Packet->m_PosY, a_Packet->m_PosZ); + break; } - break; - default: - break; - }; - } + default: + { + break; + } + } // switch (BlockID) + } // if (Direction >= 0) // Some checks to see if it's a placeable item :P if (bPlaceBlock) @@ -950,7 +948,7 @@ void cClientHandle::HandleBlockPlace(cPacket_BlockPlace * a_Packet) cItem Item; Item.m_ItemID = Equipped.m_ItemID; Item.m_ItemCount = 1; - LOG("a_Packet->m_ItemType: %i", (int)a_Packet->m_ItemType); + LOG("Placing item of type: %i", (int)a_Packet->m_ItemType); // Hacked in edible items go!~ // TODO: Handle hunger @@ -958,68 +956,68 @@ void cClientHandle::HandleBlockPlace(cPacket_BlockPlace * a_Packet) bool isDoor = false; switch (Item.m_ItemID) { - case E_ITEM_APPLE: - //m_Player->Heal(4); // 2 hearts - m_Player->Feed(24); // 2 food bars - bEat = true; - break; - case E_ITEM_GOLDEN_APPLE: - //m_Player->Heal(20); // 10 hearts - m_Player->Feed(60); // 5 food - bEat = true; - break; - case E_ITEM_MUSHROOM_SOUP: - ///m_Player->Heal(10); // 5 hearts - m_Player->Feed(48); // 4 food - bEat = true; - break; - case E_ITEM_BREAD: - //m_Player->Heal(5); // 2.5 hearts - m_Player->Feed(30); // 2.5 food - bEat = true; - break; - case E_ITEM_RAW_MEAT: - //m_Player->Heal(3); // 1.5 hearts - m_Player->Feed(18); // 1.5 food - bEat = true; - break; - case E_ITEM_COOKED_MEAT: - //m_Player->Heal(8); // 4 hearts - m_Player->Feed(48); // 4 food - bEat = true; - break; - case E_ITEM_RAW_FISH: - //m_Player->Heal(2); // 1 heart - m_Player->Feed(12); // 1 food - bEat = true; - break; - case E_ITEM_COOKED_FISH: - //m_Player->Heal(5); // 2.5 hearts - m_Player->Feed(30); // 2.5 food - bEat = true; - break; - case E_ITEM_RAW_CHICKEN: - //m_Player->Heal(3); - m_Player->Feed(12); // 1 food - bEat = true; - break; - case E_ITEM_COOKED_CHICKEN: - //m_Player->Heal(8); - m_Player->Feed(36); // 3 food - bEat = true; - break; - case E_ITEM_RAW_BEEF: - //m_Player->Heal(3); - m_Player->Feed(18); // 1.5 food - bEat = true; - break; - case E_ITEM_STEAK: - //m_Player->Heal(8); - m_Player->Feed(48); // 4 food - bEat = true; - break; - default: - break; + case E_ITEM_APPLE: + //m_Player->Heal(4); // 2 hearts + m_Player->Feed(24); // 2 food bars + bEat = true; + break; + case E_ITEM_GOLDEN_APPLE: + //m_Player->Heal(20); // 10 hearts + m_Player->Feed(60); // 5 food + bEat = true; + break; + case E_ITEM_MUSHROOM_SOUP: + ///m_Player->Heal(10); // 5 hearts + m_Player->Feed(48); // 4 food + bEat = true; + break; + case E_ITEM_BREAD: + //m_Player->Heal(5); // 2.5 hearts + m_Player->Feed(30); // 2.5 food + bEat = true; + break; + case E_ITEM_RAW_MEAT: + //m_Player->Heal(3); // 1.5 hearts + m_Player->Feed(18); // 1.5 food + bEat = true; + break; + case E_ITEM_COOKED_MEAT: + //m_Player->Heal(8); // 4 hearts + m_Player->Feed(48); // 4 food + bEat = true; + break; + case E_ITEM_RAW_FISH: + //m_Player->Heal(2); // 1 heart + m_Player->Feed(12); // 1 food + bEat = true; + break; + case E_ITEM_COOKED_FISH: + //m_Player->Heal(5); // 2.5 hearts + m_Player->Feed(30); // 2.5 food + bEat = true; + break; + case E_ITEM_RAW_CHICKEN: + //m_Player->Heal(3); + m_Player->Feed(12); // 1 food + bEat = true; + break; + case E_ITEM_COOKED_CHICKEN: + //m_Player->Heal(8); + m_Player->Feed(36); // 3 food + bEat = true; + break; + case E_ITEM_RAW_BEEF: + //m_Player->Heal(3); + m_Player->Feed(18); // 1.5 food + bEat = true; + break; + case E_ITEM_STEAK: + //m_Player->Heal(8); + m_Player->Feed(48); // 4 food + bEat = true; + break; + default: + break; }; if (bEat) diff --git a/source/cFurnaceEntity.cpp b/source/cFurnaceEntity.cpp index d5bd192c5..4485d2c01 100644 --- a/source/cFurnaceEntity.cpp +++ b/source/cFurnaceEntity.cpp @@ -74,7 +74,7 @@ void cFurnaceEntity::Destroy() -void cFurnaceEntity::UsedBy( cPlayer & a_Player ) +void cFurnaceEntity::UsedBy( cPlayer * a_Player ) { LOG("Used a furnace"); @@ -88,11 +88,11 @@ void cFurnaceEntity::UsedBy( cPlayer & a_Player ) } if( GetWindow() ) { - if( a_Player.GetWindow() != GetWindow() ) + if( a_Player->GetWindow() != GetWindow() ) { - a_Player.OpenWindow( GetWindow() ); + a_Player->OpenWindow( GetWindow() ); - GetWindow()->SendWholeWindow( a_Player.GetClientHandle() ); + GetWindow()->SendWholeWindow( a_Player->GetClientHandle() ); } } } diff --git a/source/cFurnaceEntity.h b/source/cFurnaceEntity.h index 19b518cda..647339b75 100644 --- a/source/cFurnaceEntity.h +++ b/source/cFurnaceEntity.h @@ -37,7 +37,8 @@ public: void SaveToJson (Json::Value& a_Value ); bool Tick( float a_Dt ); - virtual void UsedBy( cPlayer & a_Player ); + + virtual void UsedBy( cPlayer * a_Player ) override; bool StartCooking(); diff --git a/source/cSignEntity.cpp b/source/cSignEntity.cpp index 463e1072a..618f5960e 100644 --- a/source/cSignEntity.cpp +++ b/source/cSignEntity.cpp @@ -35,7 +35,7 @@ cSignEntity::~cSignEntity() // It don't do anything when 'used' -void cSignEntity::UsedBy( cPlayer & a_Player ) +void cSignEntity::UsedBy( cPlayer * a_Player ) { (void)a_Player; } diff --git a/source/cSignEntity.h b/source/cSignEntity.h index 0c9e40710..33578e1be 100644 --- a/source/cSignEntity.h +++ b/source/cSignEntity.h @@ -33,8 +33,8 @@ public: AString GetLine( int a_Index ) const; - virtual void UsedBy( cPlayer & a_Player ); - virtual void SendTo( cClientHandle* a_Client ); + virtual void UsedBy( cPlayer * a_Player ) override; + virtual void SendTo( cClientHandle* a_Client ) override; private: diff --git a/source/cWorld.h b/source/cWorld.h index b8c1391fd..453b30a2a 100644 --- a/source/cWorld.h +++ b/source/cWorld.h @@ -67,6 +67,8 @@ public: void Broadcast( const cPacket & a_Packet, cClientHandle* a_Exclude = 0 ); + void BroadcastToChunkOfBlock(int a_X, int a_Y, int a_Z, cPacket * a_Packet, cClientHandle * a_Exclude = NULL) {return m_ChunkMap->BroadcastToChunkOfBlock(a_X, a_Y, a_Z, a_Packet, a_Exclude); } + // MOTD const AString & GetDescription(void) const {return m_Description; } @@ -117,6 +119,9 @@ public: // TODO: This interface is dangerous! cBlockEntity * GetBlockEntity( int a_X, int a_Y, int a_Z ); //tolua_export + + /// a_Player is using block entity at [x, y, z], handle that: + void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z) {m_ChunkMap->UseBlockEntity(a_Player, a_X, a_Y, a_Z); } void GrowTree( int a_X, int a_Y, int a_Z ); //tolua_export