diff options
author | Mattes D <github@xoft.cz> | 2014-03-07 17:54:10 +0100 |
---|---|---|
committer | Mattes D <github@xoft.cz> | 2014-03-07 17:54:10 +0100 |
commit | f72c747b5005df8bc53a9e38e52fc47ceae8515c (patch) | |
tree | 6abf8ca1a3f2bd35c059bffe226b26a4c553e723 /src | |
parent | Fixed a typo. (diff) | |
parent | Link cItem in the documentation (diff) | |
download | cuberite-f72c747b5005df8bc53a9e38e52fc47ceae8515c.tar cuberite-f72c747b5005df8bc53a9e38e52fc47ceae8515c.tar.gz cuberite-f72c747b5005df8bc53a9e38e52fc47ceae8515c.tar.bz2 cuberite-f72c747b5005df8bc53a9e38e52fc47ceae8515c.tar.lz cuberite-f72c747b5005df8bc53a9e38e52fc47ceae8515c.tar.xz cuberite-f72c747b5005df8bc53a9e38e52fc47ceae8515c.tar.zst cuberite-f72c747b5005df8bc53a9e38e52fc47ceae8515c.zip |
Diffstat (limited to '')
-rw-r--r-- | src/Bindings/AllToLua.pkg | 2 | ||||
-rw-r--r-- | src/Bindings/ManualBindings.cpp | 4 | ||||
-rw-r--r-- | src/BlockEntities/BlockEntity.cpp | 2 | ||||
-rw-r--r-- | src/BlockEntities/FlowerPotEntity.cpp | 134 | ||||
-rw-r--r-- | src/BlockEntities/FlowerPotEntity.h | 74 | ||||
-rw-r--r-- | src/Blocks/BlockFlowerPot.h | 83 | ||||
-rw-r--r-- | src/Blocks/BlockMobHead.h | 5 | ||||
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/Chunk.cpp | 37 | ||||
-rw-r--r-- | src/Chunk.h | 11 | ||||
-rw-r--r-- | src/ChunkMap.cpp | 22 | ||||
-rw-r--r-- | src/ChunkMap.h | 9 | ||||
-rw-r--r-- | src/Protocol/Protocol17x.cpp | 16 | ||||
-rw-r--r-- | src/World.cpp | 13 | ||||
-rw-r--r-- | src/World.h | 13 | ||||
-rw-r--r-- | src/WorldStorage/NBTChunkSerializer.cpp | 15 | ||||
-rw-r--r-- | src/WorldStorage/NBTChunkSerializer.h | 2 | ||||
-rw-r--r-- | src/WorldStorage/WSSAnvil.cpp | 36 | ||||
-rw-r--r-- | src/WorldStorage/WSSAnvil.h | 1 | ||||
-rw-r--r-- | src/WorldStorage/WSSCompact.cpp | 40 |
20 files changed, 419 insertions, 101 deletions
diff --git a/src/Bindings/AllToLua.pkg b/src/Bindings/AllToLua.pkg index 6b067b1e5..2676281f9 100644 --- a/src/Bindings/AllToLua.pkg +++ b/src/Bindings/AllToLua.pkg @@ -58,6 +58,8 @@ $cfile "../BlockEntities/HopperEntity.h" $cfile "../BlockEntities/JukeboxEntity.h" $cfile "../BlockEntities/NoteEntity.h" $cfile "../BlockEntities/SignEntity.h" +$cfile "../BlockEntities/MobHeadEntity.h" +$cfile "../BlockEntities/FlowerPotEntity.h" $cfile "../WebAdmin.h" $cfile "../Root.h" $cfile "../Vector3f.h" diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index 0dcb336ef..05dc9717e 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -23,6 +23,7 @@ #include "../BlockEntities/HopperEntity.h" #include "../BlockEntities/NoteEntity.h" #include "../BlockEntities/MobHeadEntity.h" +#include "../BlockEntities/FlowerPotEntity.h" #include "md5/md5.h" #include "../LineBlockTracer.h" #include "../WorldStorage/SchematicFileSerializer.h" @@ -2880,7 +2881,8 @@ void ManualBindings::Bind(lua_State * tolua_S) tolua_function(tolua_S, "DoWithFurnaceAt", tolua_DoWithXYZ<cWorld, cFurnaceEntity, &cWorld::DoWithFurnaceAt>); tolua_function(tolua_S, "DoWithNoteBlockAt", tolua_DoWithXYZ<cWorld, cNoteEntity, &cWorld::DoWithNoteBlockAt>); tolua_function(tolua_S, "DoWithCommandBlockAt", tolua_DoWithXYZ<cWorld, cCommandBlockEntity, &cWorld::DoWithCommandBlockAt>); - tolua_function(tolua_S, "DoWithMobHeadBlockAt", tolua_DoWithXYZ<cWorld, cMobHeadEntity, &cWorld::DoWithMobHeadBlockAt>); + tolua_function(tolua_S, "DoWithMobHeadAt", tolua_DoWithXYZ<cWorld, cMobHeadEntity, &cWorld::DoWithMobHeadAt>); + tolua_function(tolua_S, "DoWithFlowerPotAt", tolua_DoWithXYZ<cWorld, cFlowerPotEntity, &cWorld::DoWithFlowerPotAt>); 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<cWorld, cBlockEntity, &cWorld::ForEachBlockEntityInChunk>); diff --git a/src/BlockEntities/BlockEntity.cpp b/src/BlockEntities/BlockEntity.cpp index 57ad83de9..b42318c2f 100644 --- a/src/BlockEntities/BlockEntity.cpp +++ b/src/BlockEntities/BlockEntity.cpp @@ -10,6 +10,7 @@ #include "DispenserEntity.h" #include "DropperEntity.h" #include "EnderChestEntity.h" +#include "FlowerPotEntity.h" #include "FurnaceEntity.h" #include "HopperEntity.h" #include "JukeboxEntity.h" @@ -30,6 +31,7 @@ cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE case E_BLOCK_DISPENSER: return new cDispenserEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); case E_BLOCK_DROPPER: return new cDropperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); case E_BLOCK_ENDER_CHEST: return new cEnderChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); + case E_BLOCK_FLOWER_POT: return new cFlowerPotEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); case E_BLOCK_HEAD: return new cMobHeadEntity (a_BlockX, a_BlockY, a_BlockZ, a_World); case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World); case E_BLOCK_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World); diff --git a/src/BlockEntities/FlowerPotEntity.cpp b/src/BlockEntities/FlowerPotEntity.cpp new file mode 100644 index 000000000..87bf8b921 --- /dev/null +++ b/src/BlockEntities/FlowerPotEntity.cpp @@ -0,0 +1,134 @@ + +// FlowerPotEntity.cpp + +// Implements the cFlowerPotEntity class representing a single sign in the world + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules +#include "json/json.h" +#include "FlowerPotEntity.h" +#include "../Entities/Player.h" +#include "../Item.h" + + + + + +cFlowerPotEntity::cFlowerPotEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) : + super(E_BLOCK_FLOWER_POT, a_BlockX, a_BlockY, a_BlockZ, a_World) +{ +} + + + + + +// It don't do anything when 'used' +void cFlowerPotEntity::UsedBy(cPlayer * a_Player) +{ + if (IsItemInPot()) + { + return; + } + + cItem SelectedItem = a_Player->GetInventory().GetEquippedItem(); + if (IsFlower(SelectedItem.m_ItemType, SelectedItem.m_ItemDamage)) + { + m_Item = SelectedItem.CopyOne(); + if (!a_Player->IsGameModeCreative()) + { + a_Player->GetInventory().RemoveOneEquippedItem(); + } + m_World->BroadcastBlockEntity(m_PosX, m_PosY, m_PosZ, a_Player->GetClientHandle()); + } +} + + + + + +void cFlowerPotEntity::SendTo(cClientHandle & a_Client) +{ + a_Client.SendUpdateBlockEntity(*this); +} + + + + + +void cFlowerPotEntity::Destroy(void) +{ + // Drop the contents as pickups: + if (!m_Item.IsEmpty()) + { + ASSERT(m_World != NULL); + cItems Pickups; + Pickups.Add(m_Item); + m_World->SpawnItemPickups(Pickups, m_PosX + 0.5, m_PosY + 0.5, m_PosZ + 0.5); + + m_Item.Empty(); + } +} + + + + + +bool cFlowerPotEntity::LoadFromJson(const Json::Value & a_Value) +{ + m_PosX = a_Value.get("x", 0).asInt(); + m_PosY = a_Value.get("y", 0).asInt(); + m_PosZ = a_Value.get("z", 0).asInt(); + + m_Item = cItem(); + m_Item.FromJson(a_Value.get("Item", 0)); + + return true; +} + + + + + +void cFlowerPotEntity::SaveToJson(Json::Value & a_Value) +{ + a_Value["x"] = m_PosX; + a_Value["y"] = m_PosY; + a_Value["z"] = m_PosZ; + + Json::Value Item; + m_Item.GetJson(Item); + a_Value["Item"] = Item; +} + + + + + +bool cFlowerPotEntity::IsFlower(short m_ItemType, short m_ItemData) +{ + switch (m_ItemType) + { + case E_BLOCK_DANDELION: + case E_BLOCK_FLOWER: + case E_BLOCK_CACTUS: + case E_BLOCK_BROWN_MUSHROOM: + case E_BLOCK_RED_MUSHROOM: + case E_BLOCK_SAPLING: + case E_BLOCK_DEAD_BUSH: + { + return true; + } + case E_BLOCK_TALL_GRASS: + { + return (m_ItemData == (short) 2); + } + default: + { + return false; + } + } +} + + + + diff --git a/src/BlockEntities/FlowerPotEntity.h b/src/BlockEntities/FlowerPotEntity.h new file mode 100644 index 000000000..da3fe9b7e --- /dev/null +++ b/src/BlockEntities/FlowerPotEntity.h @@ -0,0 +1,74 @@ +// FlowerPotEntity.h + +// Declares the cFlowerPotEntity class representing a single sign in the world + + + + + +#pragma once + +#include "BlockEntity.h" + +class cItem; + + + + + +namespace Json +{ + class Value; +} + + + + + +// tolua_begin + +class cFlowerPotEntity : + public cBlockEntity +{ + typedef cBlockEntity super; + +public: + + // tolua_end + + /** Creates a new flowerpot entity at the specified block coords. a_World may be NULL */ + cFlowerPotEntity(int a_BlocX, int a_BlockY, int a_BlockZ, cWorld * a_World); + + bool LoadFromJson( const Json::Value& a_Value ); + virtual void SaveToJson(Json::Value& a_Value ) override; + + virtual void Destroy(void) override; + + // tolua_begin + + /** Is a flower in the pot? */ + bool IsItemInPot(void) { return !m_Item.IsEmpty(); } + + /** Get the item in the flower pot */ + cItem GetItem(void) const { return m_Item; } + + /** Set the item in the flower pot */ + void SetItem(const cItem a_Item) { m_Item = a_Item; } + + // tolua_end + + virtual void UsedBy(cPlayer * a_Player) override; + virtual void SendTo(cClientHandle & a_Client) override; + + static bool IsFlower(short m_ItemType, short m_ItemData); + + static const char * GetClassStatic(void) { return "cFlowerPotEntity"; } + +private: + + cItem m_Item; +} ; // tolua_export + + + + diff --git a/src/Blocks/BlockFlowerPot.h b/src/Blocks/BlockFlowerPot.h index 4de85f629..fc75ef638 100644 --- a/src/Blocks/BlockFlowerPot.h +++ b/src/Blocks/BlockFlowerPot.h @@ -2,101 +2,24 @@ #pragma once #include "BlockHandler.h" +#include "BlockEntity.h" class cBlockFlowerPotHandler : - public cBlockHandler + public cBlockEntityHandler { public: cBlockFlowerPotHandler(BLOCKTYPE a_BlockType) : - cBlockHandler(a_BlockType) + cBlockEntityHandler(a_BlockType) { } - virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override { a_Pickups.push_back(cItem(E_ITEM_FLOWER_POT, 1, 0)); - if (a_BlockMeta == 0) - { - return; - } - cItem Plant; - switch (a_BlockMeta) - { - case 1: Plant = cItem(E_BLOCK_RED_ROSE, 1, 0); break; - case 2: Plant = cItem(E_BLOCK_YELLOW_FLOWER, 1, 0); break; - case 3: Plant = cItem(E_BLOCK_SAPLING, 1, E_META_SAPLING_APPLE); break; - case 4: Plant = cItem(E_BLOCK_SAPLING, 1, E_META_SAPLING_CONIFER); break; - case 5: Plant = cItem(E_BLOCK_SAPLING, 1, E_META_SAPLING_BIRCH); break; - case 6: Plant = cItem(E_BLOCK_SAPLING, 1, E_META_SAPLING_JUNGLE); break; - case 7: Plant = cItem(E_BLOCK_RED_MUSHROOM, 1, 0); break; - case 8: Plant = cItem(E_BLOCK_BROWN_MUSHROOM, 1, 0); break; - case 9: Plant = cItem(E_BLOCK_CACTUS, 1, 0); break; - case 10: Plant = cItem(E_BLOCK_DEAD_BUSH, 1, 0); break; - case 11: Plant = cItem(E_BLOCK_TALL_GRASS, 1, E_META_TALL_GRASS_FERN); break; - default: return; - } - a_Pickups.push_back(Plant); - } - - - void OnUse(cWorld * a_World, cWorldInterface * a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) - { - NIBBLETYPE Meta = a_World->GetBlockMeta( a_BlockX, a_BlockY, a_BlockZ ); - if (Meta != 0) - { - // Already filled - return; - } - - switch (a_Player->GetEquippedItem().m_ItemType) - { - case E_BLOCK_RED_ROSE: Meta = 1; break; - case E_BLOCK_YELLOW_FLOWER: Meta = 2; break; - case E_BLOCK_SAPLING: - { - switch (a_Player->GetEquippedItem().m_ItemDamage) - { - case E_META_SAPLING_APPLE: Meta = 3; break; - case E_META_SAPLING_CONIFER: Meta = 4; break; - case E_META_SAPLING_BIRCH: Meta = 5; break; - case E_META_SAPLING_JUNGLE: Meta = 6; break; - } - break; - } - case E_BLOCK_RED_MUSHROOM: Meta = 7; break; - case E_BLOCK_BROWN_MUSHROOM: Meta = 8; break; - case E_BLOCK_CACTUS: Meta = 9; break; - case E_BLOCK_DEAD_BUSH: Meta = 10; break; - case E_BLOCK_TALL_GRASS: - { - if (a_Player->GetEquippedItem().m_ItemDamage == E_META_TALL_GRASS_FERN) - { - Meta = 11; - } - else - { - return; - } - break; - } - } - - if (a_Player->GetGameMode() != gmCreative) - { - a_Player->GetInventory().RemoveOneEquippedItem(); - } - a_World->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta); - } - - - virtual bool IsUseable(void) override - { - return true; } } ; diff --git a/src/Blocks/BlockMobHead.h b/src/Blocks/BlockMobHead.h index 6a00c3acd..2b128f13b 100644 --- a/src/Blocks/BlockMobHead.h +++ b/src/Blocks/BlockMobHead.h @@ -29,7 +29,7 @@ public: BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) override { - class cCallback : public cMobHeadBlockCallback + class cCallback : public cMobHeadCallback { cPlayer * m_Player; NIBBLETYPE m_OldBlockMeta; @@ -45,6 +45,7 @@ public: a_MobHeadEntity->SetType(static_cast<eMobHeadType>(m_OldBlockMeta)); a_MobHeadEntity->SetRotation(static_cast<eMobHeadRotation>(Rotation)); + a_MobHeadEntity->GetWorld()->BroadcastBlockEntity(a_MobHeadEntity->GetPosX(), a_MobHeadEntity->GetPosY(), a_MobHeadEntity->GetPosZ(), m_Player->GetClientHandle()); return false; } @@ -59,7 +60,7 @@ public: a_BlockMeta = a_BlockFace; cWorld * World = (cWorld *) &a_WorldInterface; - World->DoWithMobHeadBlockAt(a_BlockX, a_BlockY, a_BlockZ, Callback); + World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, Callback); a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta); } } ; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5e0731264..5029906aa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -40,6 +40,7 @@ if (NOT MSVC) BlockEntities/NoteEntity.h BlockEntities/SignEntity.h BlockEntities/MobHeadEntity.h + BlockEntities/FlowerPotEntity.h BlockID.h BoundingBox.h ChatColor.h diff --git a/src/Chunk.cpp b/src/Chunk.cpp index a75828461..957d7d575 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -20,6 +20,7 @@ #include "BlockEntities/NoteEntity.h" #include "BlockEntities/SignEntity.h" #include "BlockEntities/MobHeadEntity.h" +#include "BlockEntities/FlowerPotEntity.h" #include "Entities/Pickup.h" #include "Item.h" #include "Noise.h" @@ -1311,6 +1312,7 @@ void cChunk::CreateBlockEntities(void) case E_BLOCK_HEAD: case E_BLOCK_NOTE_BLOCK: case E_BLOCK_JUKEBOX: + case E_BLOCK_FLOWER_POT: { if (!HasBlockEntityAt(x + m_PosX * Width, y + m_PosY * Height, z + m_PosZ * Width)) { @@ -1440,6 +1442,7 @@ void cChunk::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, case E_BLOCK_HEAD: case E_BLOCK_NOTE_BLOCK: case E_BLOCK_JUKEBOX: + case E_BLOCK_FLOWER_POT: { AddBlockEntity(cBlockEntity::CreateByBlockType(a_BlockType, a_BlockMeta, WorldPos.x, WorldPos.y, WorldPos.z, m_World)); break; @@ -2337,7 +2340,7 @@ bool cChunk::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCom -bool cChunk::DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadBlockCallback & a_Callback) +bool cChunk::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & 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) @@ -2369,6 +2372,38 @@ bool cChunk::DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMob +bool cChunk::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & 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_FLOWER_POT) + { + // 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((cFlowerPotEntity *)*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 c9e9697ca..b3fa563cc 100644 --- a/src/Chunk.h +++ b/src/Chunk.h @@ -32,6 +32,7 @@ class cDispenserEntity; class cFurnaceEntity; class cNoteEntity; class cMobHeadEntity; +class cFlowerPotEntity; class cBlockArea; class cPawn; class cPickup; @@ -48,7 +49,8 @@ typedef cItemCallback<cDispenserEntity> cDispenserCallback; typedef cItemCallback<cFurnaceEntity> cFurnaceCallback; typedef cItemCallback<cNoteEntity> cNoteBlockCallback; typedef cItemCallback<cCommandBlockEntity> cCommandBlockCallback; -typedef cItemCallback<cMobHeadEntity> cMobHeadBlockCallback; +typedef cItemCallback<cMobHeadEntity> cMobHeadCallback; +typedef cItemCallback<cFlowerPotEntity> cFlowerPotCallback; @@ -253,8 +255,11 @@ public: /** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */ bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback); - /** Calls the callback for the mob head block at the specified coords; returns false if there's no mob header block at those coords or callback returns true, returns true if found */ - bool DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadBlockCallback & a_Callback); + /** Calls the callback for the mob head block at the specified coords; returns false if there's no mob head block at those coords or callback returns true, returns true if found */ + bool DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback); + + /** Calls the callback for the flower pot at the specified coords; returns false if there's no flower pot at those coords or callback returns true, returns true if found */ + bool DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & 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 b5795fbaf..40964c654 100644 --- a/src/ChunkMap.cpp +++ b/src/ChunkMap.cpp @@ -2182,7 +2182,7 @@ bool cChunkMap::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, c -bool cChunkMap::DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadBlockCallback & a_Callback) +bool cChunkMap::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback) { int ChunkX, ChunkZ; int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ; @@ -2193,7 +2193,25 @@ bool cChunkMap::DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, c { return false; } - return Chunk->DoWithMobHeadBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); + return Chunk->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); +} + + + + + +bool cChunkMap::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & 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->DoWithFlowerPotAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); } diff --git a/src/ChunkMap.h b/src/ChunkMap.h index 9df68c403..9d973f2a9 100644 --- a/src/ChunkMap.h +++ b/src/ChunkMap.h @@ -26,6 +26,7 @@ class cFurnaceEntity; class cNoteEntity; class cCommandBlockEntity; class cMobHeadEntity; +class cFlowerPotEntity; class cPawn; class cPickup; class cChunkDataSerializer; @@ -41,10 +42,11 @@ typedef cItemCallback<cChestEntity> cChestCallback; typedef cItemCallback<cDispenserEntity> cDispenserCallback; typedef cItemCallback<cDropperEntity> cDropperCallback; typedef cItemCallback<cDropSpenserEntity> cDropSpenserCallback; +typedef cItemCallback<cFlowerPotEntity> cFlowerPotCallback; typedef cItemCallback<cFurnaceEntity> cFurnaceCallback; typedef cItemCallback<cNoteEntity> cNoteBlockCallback; typedef cItemCallback<cCommandBlockEntity> cCommandBlockCallback; -typedef cItemCallback<cMobHeadEntity> cMobHeadBlockCallback; +typedef cItemCallback<cMobHeadEntity> cMobHeadCallback; typedef cItemCallback<cChunk> cChunkCallback; @@ -257,7 +259,10 @@ public: bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback); // Lua-accessible /** Calls the callback for the mob head block at the specified coords; returns false if there's no mob head block at those coords or callback returns true, returns true if found */ - bool DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadBlockCallback & a_Callback); // Lua-accessible + bool DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback); // Lua-accessible + + /** Calls the callback for the flower pot at the specified coords; returns false if there's no flower pot at those coords or callback returns true, returns true if found */ + bool DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & 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/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 992023464..18646254f 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -29,6 +29,7 @@ Implements the 1.7.x protocol classes: #include "../UI/Window.h" #include "../BlockEntities/CommandBlockEntity.h" #include "../BlockEntities/MobHeadEntity.h" +#include "../BlockEntities/FlowerPotEntity.h" #include "../CompositeChat.h" @@ -1115,6 +1116,7 @@ void cProtocol172::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) case E_BLOCK_MOB_SPAWNER: Action = 1; break; // Update mob spawner spinny mob thing case E_BLOCK_COMMAND_BLOCK: Action = 2; break; // Update command block text case E_BLOCK_HEAD: Action = 4; break; // Update Mobhead entity + case E_BLOCK_FLOWER_POT: Action = 5; break; // Update flower pot default: ASSERT(!"Unhandled or unimplemented BlockEntity update request!"); break; } Pkt.WriteByte(Action); @@ -2345,7 +2347,7 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt case E_BLOCK_HEAD: { cMobHeadEntity & MobHeadEntity = (cMobHeadEntity &)a_BlockEntity; - + Writer.AddInt("x", MobHeadEntity.GetPosX()); Writer.AddInt("y", MobHeadEntity.GetPosY()); Writer.AddInt("z", MobHeadEntity.GetPosZ()); @@ -2355,6 +2357,18 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt Writer.AddString("id", "Skull"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though break; } + case E_BLOCK_FLOWER_POT: + { + cFlowerPotEntity & FlowerPotEntity = (cFlowerPotEntity &)a_BlockEntity; + + Writer.AddInt("x", FlowerPotEntity.GetPosX()); + Writer.AddInt("y", FlowerPotEntity.GetPosY()); + Writer.AddInt("z", FlowerPotEntity.GetPosZ()); + Writer.AddInt("Item", (Int32) FlowerPotEntity.GetItem().m_ItemType); + Writer.AddInt("Data", (Int32) FlowerPotEntity.GetItem().m_ItemDamage); + Writer.AddString("id", "FlowerPot"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though + break; + } default: break; } diff --git a/src/World.cpp b/src/World.cpp index 73157b5bf..f6d277663 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1198,9 +1198,18 @@ bool cWorld::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCom -bool cWorld::DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadBlockCallback & a_Callback) +bool cWorld::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback) { - return m_ChunkMap->DoWithMobHeadBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); + return m_ChunkMap->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); +} + + + + + +bool cWorld::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & a_Callback) +{ + return m_ChunkMap->DoWithFlowerPotAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); } diff --git a/src/World.h b/src/World.h index 69d0d6b41..0a0939dd1 100644 --- a/src/World.h +++ b/src/World.h @@ -44,6 +44,7 @@ class cWorldGenerator; // The generator that actually generates the chunks for class cChunkGenerator; // The thread responsible for generating chunks class cChestEntity; class cDispenserEntity; +class cFlowerPotEntity; class cFurnaceEntity; class cNoteEntity; class cMobHeadEntity; @@ -60,7 +61,8 @@ typedef cItemCallback<cDispenserEntity> cDispenserCallback; typedef cItemCallback<cFurnaceEntity> cFurnaceCallback; typedef cItemCallback<cNoteEntity> cNoteBlockCallback; typedef cItemCallback<cCommandBlockEntity> cCommandBlockCallback; -typedef cItemCallback<cMobHeadEntity> cMobHeadBlockCallback; +typedef cItemCallback<cMobHeadEntity> cMobHeadCallback; +typedef cItemCallback<cFlowerPotEntity> cFlowerPotCallback; @@ -531,10 +533,13 @@ public: /** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */ bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback); // Exported in ManualBindings.cpp - + /** Calls the callback for the mob head block at the specified coords; returns false if there's no mob head block at those coords or callback returns true, returns true if found */ - bool DoWithMobHeadBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadBlockCallback & a_Callback); // Exported in ManualBindings.cpp - + bool DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback); // Exported in ManualBindings.cpp + + /** Calls the callback for the flower pot at the specified coords; returns false if there's no flower pot at those coords or callback returns true, returns true if found */ + bool DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback & 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 diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index c1c659b36..6d0e29958 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -20,6 +20,7 @@ #include "../BlockEntities/NoteEntity.h" #include "../BlockEntities/SignEntity.h" #include "../BlockEntities/MobHeadEntity.h" +#include "../BlockEntities/FlowerPotEntity.h" #include "../Entities/Entity.h" #include "../Entities/FallingBlock.h" @@ -275,6 +276,19 @@ void cNBTChunkSerializer::AddMobHeadEntity(cMobHeadEntity * a_MobHead) +void cNBTChunkSerializer::AddFlowerPotEntity(cFlowerPotEntity * a_FlowerPot) +{ + m_Writer.BeginCompound(""); + AddBasicTileEntity(a_FlowerPot, "FlowerPot"); + m_Writer.AddInt ("Item", (Int32) a_FlowerPot->GetItem().m_ItemType); + m_Writer.AddInt ("Data", (Int32) a_FlowerPot->GetItem().m_ItemDamage); + m_Writer.EndCompound(); +} + + + + + void cNBTChunkSerializer::AddBasicEntity(cEntity * a_Entity, const AString & a_ClassName) { m_Writer.AddString("id", a_ClassName); @@ -687,6 +701,7 @@ void cNBTChunkSerializer::BlockEntity(cBlockEntity * a_Entity) case E_BLOCK_CHEST: AddChestEntity ((cChestEntity *) a_Entity); break; case E_BLOCK_DISPENSER: AddDispenserEntity ((cDispenserEntity *) a_Entity); break; case E_BLOCK_DROPPER: AddDropperEntity ((cDropperEntity *) a_Entity); break; + case E_BLOCK_FLOWER_POT: AddFlowerPotEntity ((cFlowerPotEntity *) a_Entity); break; case E_BLOCK_FURNACE: AddFurnaceEntity ((cFurnaceEntity *) a_Entity); break; case E_BLOCK_HOPPER: AddHopperEntity ((cHopperEntity *) a_Entity); break; case E_BLOCK_SIGN_POST: diff --git a/src/WorldStorage/NBTChunkSerializer.h b/src/WorldStorage/NBTChunkSerializer.h index 5f9e16ed1..8a9e18413 100644 --- a/src/WorldStorage/NBTChunkSerializer.h +++ b/src/WorldStorage/NBTChunkSerializer.h @@ -30,6 +30,7 @@ class cJukeboxEntity; class cNoteEntity; class cSignEntity; class cMobHeadEntity; +class cFlowerPotEntity; class cFallingBlock; class cMinecart; class cMinecartWithChest; @@ -96,6 +97,7 @@ protected: void AddSignEntity (cSignEntity * a_Sign); void AddMobHeadEntity (cMobHeadEntity * a_MobHead); void AddCommandBlockEntity(cCommandBlockEntity * a_CmdBlock); + void AddFlowerPotEntity(cFlowerPotEntity * a_FlowerPot); // Entities: void AddBasicEntity (cEntity * a_Entity, const AString & a_ClassName); diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 05332d23d..680f2458f 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -25,6 +25,7 @@ #include "../BlockEntities/NoteEntity.h" #include "../BlockEntities/SignEntity.h" #include "../BlockEntities/MobHeadEntity.h" +#include "../BlockEntities/FlowerPotEntity.h" #include "../Mobs/Monster.h" @@ -578,6 +579,10 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con { LoadDropperFromNBT(a_BlockEntities, a_NBT, Child); } + else if (strncmp(a_NBT.GetData(sID), "FlowerPot", a_NBT.GetDataLength(sID)) == 0) + { + LoadFlowerPotFromNBT(a_BlockEntities, a_NBT, Child); + } else if (strncmp(a_NBT.GetData(sID), "Furnace", a_NBT.GetDataLength(sID)) == 0) { LoadFurnaceFromNBT(a_BlockEntities, a_NBT, Child, a_BlockTypes, a_BlockMetas); @@ -760,6 +765,37 @@ void cWSSAnvil::LoadDropperFromNBT(cBlockEntityList & a_BlockEntities, const cPa +void cWSSAnvil::LoadFlowerPotFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx) +{ + ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound); + int x, y, z; + if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z)) + { + return; + } + std::auto_ptr<cFlowerPotEntity> FlowerPot(new cFlowerPotEntity(x, y, z, m_World)); + short ItemType = 0, ItemData = 0; + + int currentLine = a_NBT.FindChildByName(a_TagIdx, "Item"); + if (currentLine >= 0) + { + ItemType = (short) a_NBT.GetInt(currentLine); + } + + currentLine = a_NBT.FindChildByName(a_TagIdx, "Data"); + if (currentLine >= 0) + { + ItemData = (short) a_NBT.GetInt(currentLine); + } + + FlowerPot->SetItem(cItem(ItemType, 1, ItemData)); + a_BlockEntities.push_back(FlowerPot.release()); +} + + + + + void cWSSAnvil::LoadFurnaceFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE * a_BlockTypes, NIBBLETYPE * a_BlockMetas) { ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound); diff --git a/src/WorldStorage/WSSAnvil.h b/src/WorldStorage/WSSAnvil.h index 4acf3f2a1..b26345b13 100644 --- a/src/WorldStorage/WSSAnvil.h +++ b/src/WorldStorage/WSSAnvil.h @@ -135,6 +135,7 @@ protected: void LoadChestFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadDispenserFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadDropperFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); + void LoadFlowerPotFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadFurnaceFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE * a_BlockTypes, NIBBLETYPE * a_BlockMetas); void LoadHopperFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadJukeboxFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); diff --git a/src/WorldStorage/WSSCompact.cpp b/src/WorldStorage/WSSCompact.cpp index 4c0684dd8..5e49e4909 100644 --- a/src/WorldStorage/WSSCompact.cpp +++ b/src/WorldStorage/WSSCompact.cpp @@ -12,8 +12,10 @@ #include "../BlockEntities/ChestEntity.h" #include "../BlockEntities/CommandBlockEntity.h" #include "../BlockEntities/DispenserEntity.h" +#include "../BlockEntities/FlowerPotEntity.h" #include "../BlockEntities/FurnaceEntity.h" #include "../BlockEntities/JukeboxEntity.h" +#include "../BlockEntities/MobHeadEntity.h" #include "../BlockEntities/NoteEntity.h" #include "../BlockEntities/SignEntity.h" @@ -75,12 +77,14 @@ void cJsonChunkSerializer::BlockEntity(cBlockEntity * a_BlockEntity) case E_BLOCK_CHEST: SaveInto = "Chests"; break; case E_BLOCK_DISPENSER: SaveInto = "Dispensers"; break; case E_BLOCK_DROPPER: SaveInto = "Droppers"; break; + case E_BLOCK_FLOWER_POT: SaveInto = "FlowerPots"; break; case E_BLOCK_FURNACE: SaveInto = "Furnaces"; break; case E_BLOCK_SIGN_POST: SaveInto = "Signs"; break; case E_BLOCK_WALLSIGN: SaveInto = "Signs"; break; case E_BLOCK_NOTE_BLOCK: SaveInto = "Notes"; break; case E_BLOCK_JUKEBOX: SaveInto = "Jukeboxes"; break; case E_BLOCK_COMMAND_BLOCK: SaveInto = "CommandBlocks"; break; + case E_BLOCK_HEAD: SaveInto = "MobHeads"; break; default: { @@ -298,6 +302,21 @@ void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_En } } // for itr - AllDispensers[] + // Load Flowerpots: + Json::Value AllFlowerPots = a_Value.get("FlowerPots", Json::nullValue); + for (Json::Value::iterator itr = AllFlowerPots.begin(); itr != AllFlowerPots.end(); ++itr) + { + std::auto_ptr<cFlowerPotEntity> FlowerPotEntity(new cFlowerPotEntity(0, 0, 0, a_World)); + if (!FlowerPotEntity->LoadFromJson(*itr)) + { + LOGWARNING("ERROR READING FLOWERPOT FROM JSON!" ); + } + else + { + a_BlockEntities.push_back(FlowerPotEntity.release()); + } + } // for itr - AllFlowerPots[] + // Load furnaces: Json::Value AllFurnaces = a_Value.get("Furnaces", Json::nullValue); for (Json::Value::iterator itr = AllFurnaces.begin(); itr != AllFurnaces.end(); ++itr) @@ -331,7 +350,7 @@ void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_En // Load note blocks: Json::Value AllNotes = a_Value.get("Notes", Json::nullValue); - for( Json::Value::iterator itr = AllNotes.begin(); itr != AllNotes.end(); ++itr ) + for (Json::Value::iterator itr = AllNotes.begin(); itr != AllNotes.end(); ++itr) { std::auto_ptr<cNoteEntity> NoteEntity(new cNoteEntity(0, 0, 0, a_World)); if (!NoteEntity->LoadFromJson(*itr)) @@ -346,7 +365,7 @@ void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_En // Load jukeboxes: Json::Value AllJukeboxes = a_Value.get("Jukeboxes", Json::nullValue); - for( Json::Value::iterator itr = AllJukeboxes.begin(); itr != AllJukeboxes.end(); ++itr ) + for (Json::Value::iterator itr = AllJukeboxes.begin(); itr != AllJukeboxes.end(); ++itr) { std::auto_ptr<cJukeboxEntity> JukeboxEntity(new cJukeboxEntity(0, 0, 0, a_World)); if (!JukeboxEntity->LoadFromJson(*itr)) @@ -361,7 +380,7 @@ void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_En // Load command blocks: Json::Value AllCommandBlocks = a_Value.get("CommandBlocks", Json::nullValue); - for( Json::Value::iterator itr = AllCommandBlocks.begin(); itr != AllCommandBlocks.end(); ++itr ) + for (Json::Value::iterator itr = AllCommandBlocks.begin(); itr != AllCommandBlocks.end(); ++itr) { std::auto_ptr<cCommandBlockEntity> CommandBlockEntity(new cCommandBlockEntity(0, 0, 0, a_World)); if (!CommandBlockEntity->LoadFromJson(*itr)) @@ -373,6 +392,21 @@ void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_En a_BlockEntities.push_back(CommandBlockEntity.release()); } } // for itr - AllCommandBlocks[] + + // Load mob heads: + Json::Value AllMobHeads = a_Value.get("MobHeads", Json::nullValue); + for (Json::Value::iterator itr = AllMobHeads.begin(); itr != AllMobHeads.end(); ++itr) + { + std::auto_ptr<cMobHeadEntity> MobHeadEntity(new cMobHeadEntity(0, 0, 0, a_World)); + if (!MobHeadEntity->LoadFromJson(*itr)) + { + LOGWARNING("ERROR READING MOB HEAD FROM JSON!" ); + } + else + { + a_BlockEntities.push_back(MobHeadEntity.release()); + } + } // for itr - AllMobHeads[] } |