summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Bindings/AllToLua.pkg2
-rw-r--r--src/Bindings/ManualBindings.cpp22
-rw-r--r--src/BlockEntities/BlockEntity.cpp2
-rw-r--r--src/BlockEntities/FlowerPotEntity.cpp134
-rw-r--r--src/BlockEntities/FlowerPotEntity.h74
-rw-r--r--src/Blocks/BlockComparator.h7
-rw-r--r--src/Blocks/BlockDoor.cpp23
-rw-r--r--src/Blocks/BlockDoor.h1
-rw-r--r--src/Blocks/BlockFenceGate.h6
-rw-r--r--src/Blocks/BlockFlowerPot.h83
-rw-r--r--src/Blocks/BlockHandler.cpp10
-rw-r--r--src/Blocks/BlockHandler.h3
-rw-r--r--src/Blocks/BlockMobHead.h5
-rw-r--r--src/Blocks/BlockRedstoneRepeater.h9
-rw-r--r--src/Blocks/BlockTNT.h32
-rw-r--r--src/Blocks/BlockTrapdoor.h6
-rw-r--r--src/Blocks/WorldInterface.h3
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/Chunk.cpp37
-rw-r--r--src/Chunk.h11
-rw-r--r--src/ChunkMap.cpp22
-rw-r--r--src/ChunkMap.h9
-rw-r--r--src/ClientHandle.cpp14
-rw-r--r--src/Inventory.cpp6
-rw-r--r--src/Protocol/Protocol17x.cpp16
-rw-r--r--src/World.cpp13
-rw-r--r--src/World.h15
-rw-r--r--src/WorldStorage/NBTChunkSerializer.cpp15
-rw-r--r--src/WorldStorage/NBTChunkSerializer.h2
-rw-r--r--src/WorldStorage/SchematicFileSerializer.cpp7
-rw-r--r--src/WorldStorage/SchematicFileSerializer.h4
-rw-r--r--src/WorldStorage/WSSAnvil.cpp36
-rw-r--r--src/WorldStorage/WSSAnvil.h1
-rw-r--r--src/WorldStorage/WSSCompact.cpp40
34 files changed, 551 insertions, 120 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 f9d04ce90..a5247bbe6 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"
@@ -2456,7 +2457,7 @@ static int tolua_cBlockArea_GetSize(lua_State * tolua_S)
static int tolua_cBlockArea_LoadFromSchematicFile(lua_State * tolua_S)
{
// function cBlockArea::LoadFromSchematicFile
- // Exported manually because function has been moved to SchematicFileSerilizer.cpp
+ // Exported manually because function has been moved to SchematicFileSerializer.cpp
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cBlockArea") ||
@@ -2486,7 +2487,7 @@ static int tolua_cBlockArea_LoadFromSchematicFile(lua_State * tolua_S)
static int tolua_cBlockArea_LoadFromSchematicString(lua_State * tolua_S)
{
// function cBlockArea::LoadFromSchematicString
- // Exported manually because function has been moved to SchematicFileSerilizer.cpp
+ // Exported manually because function has been moved to SchematicFileSerializer.cpp
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cBlockArea") ||
@@ -2517,7 +2518,7 @@ static int tolua_cBlockArea_LoadFromSchematicString(lua_State * tolua_S)
static int tolua_cBlockArea_SaveToSchematicFile(lua_State * tolua_S)
{
// function cBlockArea::SaveToSchematicFile
- // Exported manually because function has been moved to SchematicFileSerilizer.cpp
+ // Exported manually because function has been moved to SchematicFileSerializer.cpp
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cBlockArea") ||
@@ -2546,7 +2547,7 @@ static int tolua_cBlockArea_SaveToSchematicFile(lua_State * tolua_S)
static int tolua_cBlockArea_SaveToSchematicString(lua_State * tolua_S)
{
// function cBlockArea::SaveToSchematicString
- // Exported manually because function has been moved to SchematicFileSerilizer.cpp
+ // Exported manually because function has been moved to SchematicFileSerializer.cpp
cLuaState L(tolua_S);
if (
!L.CheckParamUserType(1, "cBlockArea") ||
@@ -2562,9 +2563,13 @@ static int tolua_cBlockArea_SaveToSchematicString(lua_State * tolua_S)
return 0;
}
- AString Data = cSchematicFileSerializer::SaveToSchematicString(*self);
- L.Push(Data);
- return 1;
+ AString Data;
+ if (cSchematicFileSerializer::SaveToSchematicString(*self, Data))
+ {
+ L.Push(Data);
+ return 1;
+ }
+ return 0;
}
@@ -2880,7 +2885,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/BlockComparator.h b/src/Blocks/BlockComparator.h
index aba390d9d..cea35a864 100644
--- a/src/Blocks/BlockComparator.h
+++ b/src/Blocks/BlockComparator.h
@@ -26,6 +26,13 @@ public:
}
+ virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
+ {
+ UNUSED(a_ChunkInterface);
+ a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
+ }
+
+
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
diff --git a/src/Blocks/BlockDoor.cpp b/src/Blocks/BlockDoor.cpp
index 2ff5c1c37..0acf04852 100644
--- a/src/Blocks/BlockDoor.cpp
+++ b/src/Blocks/BlockDoor.cpp
@@ -55,6 +55,29 @@ void cBlockDoorHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterfac
+void cBlockDoorHandler::OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace)
+{
+ UNUSED(a_ChunkInterface);
+
+ a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
+ NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+
+ if (Meta & 8)
+ {
+ // Current block is top of the door
+ a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY - 1, a_BlockZ, a_Player);
+ }
+ else
+ {
+ // Current block is bottom of the door
+ a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, a_Player);
+ }
+}
+
+
+
+
+
void cBlockDoorHandler::OnPlacedByPlayer(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
diff --git a/src/Blocks/BlockDoor.h b/src/Blocks/BlockDoor.h
index ef0dbb787..68be2c658 100644
--- a/src/Blocks/BlockDoor.h
+++ b/src/Blocks/BlockDoor.h
@@ -16,6 +16,7 @@ public:
virtual void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
+ virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override;
virtual const char * GetStepSound(void) override;
diff --git a/src/Blocks/BlockFenceGate.h b/src/Blocks/BlockFenceGate.h
index fb984f345..1abe1eecf 100644
--- a/src/Blocks/BlockFenceGate.h
+++ b/src/Blocks/BlockFenceGate.h
@@ -48,6 +48,12 @@ public:
}
+ virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
+ {
+ a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
+ }
+
+
virtual bool IsUseable(void) override
{
return true;
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/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp
index 052f88f7a..c5165986c 100644
--- a/src/Blocks/BlockHandler.cpp
+++ b/src/Blocks/BlockHandler.cpp
@@ -57,6 +57,7 @@
#include "BlockRedstoneLamp.h"
#include "BlockRedstoneRepeater.h"
#include "BlockRedstoneTorch.h"
+#include "BlockTNT.h"
#include "BlockSand.h"
#include "BlockSapling.h"
#include "BlockSideways.h"
@@ -185,6 +186,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_TALL_GRASS: return new cBlockTallGrassHandler (a_BlockType);
case E_BLOCK_TORCH: return new cBlockTorchHandler (a_BlockType);
case E_BLOCK_TRAPDOOR: return new cBlockTrapdoorHandler (a_BlockType);
+ case E_BLOCK_TNT: return new cBlockTNTHandler (a_BlockType);
case E_BLOCK_VINES: return new cBlockVineHandler (a_BlockType);
case E_BLOCK_WALLSIGN: return new cBlockSignHandler (a_BlockType);
case E_BLOCK_WATER: return new cBlockFluidHandler (a_BlockType);
@@ -320,6 +322,14 @@ void cBlockHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface &
+void cBlockHandler::OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace)
+{
+}
+
+
+
+
+
void cBlockHandler::ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta)
{
// Setting the meta to a_BlockMeta keeps most textures. The few other blocks have to override this.
diff --git a/src/Blocks/BlockHandler.h b/src/Blocks/BlockHandler.h
index c46a46045..50c2e2ad5 100644
--- a/src/Blocks/BlockHandler.h
+++ b/src/Blocks/BlockHandler.h
@@ -69,6 +69,9 @@ public:
/// Called if the user right clicks the block and the block is useable
virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ);
+ /** Called when a Right Click to this Block is cancelled */
+ virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace);
+
/// <summary>Called when the item is mined to convert it into pickups. Pickups may specify multiple items. Appends items to a_Pickups, preserves its original contents</summary>
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta);
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/Blocks/BlockRedstoneRepeater.h b/src/Blocks/BlockRedstoneRepeater.h
index eb0918acf..1e2a86949 100644
--- a/src/Blocks/BlockRedstoneRepeater.h
+++ b/src/Blocks/BlockRedstoneRepeater.h
@@ -29,7 +29,7 @@ public:
a_BlockMeta = RepeaterRotationToMetaData(a_Player->GetYaw());
return true;
}
-
+
virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
{
@@ -37,6 +37,13 @@ public:
}
+ virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
+ {
+ UNUSED(a_ChunkInterface);
+ a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
+ }
+
+
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
diff --git a/src/Blocks/BlockTNT.h b/src/Blocks/BlockTNT.h
new file mode 100644
index 000000000..283a03730
--- /dev/null
+++ b/src/Blocks/BlockTNT.h
@@ -0,0 +1,32 @@
+
+#pragma once
+
+#include "BlockHandler.h"
+
+
+
+
+
+class cBlockTNTHandler :
+ public cBlockHandler
+{
+public:
+ cBlockTNTHandler(BLOCKTYPE a_BlockType)
+ : cBlockHandler(a_BlockType)
+ {
+ }
+
+ virtual const char * GetStepSound(void) override
+ {
+ return "step.grass";
+ }
+
+ virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
+ {
+ a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
+ }
+};
+
+
+
+
diff --git a/src/Blocks/BlockTrapdoor.h b/src/Blocks/BlockTrapdoor.h
index a28861e69..9bae92c4d 100644
--- a/src/Blocks/BlockTrapdoor.h
+++ b/src/Blocks/BlockTrapdoor.h
@@ -42,6 +42,12 @@ public:
World->BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0, a_Player->GetClientHandle());
}
+ virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
+ {
+ UNUSED(a_ChunkInterface);
+ a_WorldInterface.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
+ }
+
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
diff --git a/src/Blocks/WorldInterface.h b/src/Blocks/WorldInterface.h
index b6f2f55a7..e59b00eff 100644
--- a/src/Blocks/WorldInterface.h
+++ b/src/Blocks/WorldInterface.h
@@ -27,4 +27,7 @@ public:
/** Spawns a mob of the specified type. Returns the mob's EntityID if recognized and spawned, <0 otherwise */
virtual int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eType a_MonsterType) = 0;
+
+ /** Sends the block on those coords to the player */
+ virtual void SendBlockTo(int a_BlockX, int a_BlockY, int a_BlockZ, cPlayer * a_Player) = 0;
};
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/ClientHandle.cpp b/src/ClientHandle.cpp
index 6982a6227..870568cdf 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -920,14 +920,22 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e
a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, ItemToFullString(a_HeldItem).c_str()
);
+ cWorld * World = m_Player->GetWorld();
+
cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager();
if (PlgMgr->CallHookPlayerRightClick(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ))
{
// A plugin doesn't agree with the action, replace the block on the client and quit:
+ cChunkInterface ChunkInterface(World->GetChunkMap());
+ BLOCKTYPE BlockType = World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
+ cBlockHandler * BlockHandler = cBlockInfo::GetHandler(BlockType);
+ BlockHandler->OnCancelRightClick(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
+
if (a_BlockFace > -1)
{
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
- m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
+ World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
+ World->SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, m_Player); //2 block high things
}
return;
}
@@ -953,12 +961,10 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e
if (a_BlockFace > -1)
{
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
- m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
+ World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
}
return;
}
-
- cWorld * World = m_Player->GetWorld();
BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
diff --git a/src/Inventory.cpp b/src/Inventory.cpp
index 7f434adfd..c7c089d5f 100644
--- a/src/Inventory.cpp
+++ b/src/Inventory.cpp
@@ -204,6 +204,12 @@ void cInventory::SetSlot(int a_SlotNum, const cItem & a_Item)
return;
}
Grid->SetSlot(GridSlotNum, a_Item);
+
+ // Broadcast the Equipped Item, if the Slot is changed.
+ if ((Grid == &m_HotbarSlots) && (m_EquippedSlotNum == (a_SlotNum - invHotbarOffset)))
+ {
+ m_Owner.GetWorld()->BroadcastEntityEquipment(m_Owner, 0, a_Item, m_Owner.GetClientHandle());
+ }
}
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 93397c014..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;
@@ -455,7 +457,7 @@ public:
// tolua_begin
bool DigBlock (int a_X, int a_Y, int a_Z);
- void SendBlockTo(int a_X, int a_Y, int a_Z, cPlayer * a_Player );
+ virtual void SendBlockTo(int a_X, int a_Y, int a_Z, cPlayer * a_Player);
double GetSpawnX(void) const { return m_SpawnX; }
double GetSpawnY(void) const { return m_SpawnY; }
@@ -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/SchematicFileSerializer.cpp b/src/WorldStorage/SchematicFileSerializer.cpp
index a6ae8d8e0..b021aeb0c 100644
--- a/src/WorldStorage/SchematicFileSerializer.cpp
+++ b/src/WorldStorage/SchematicFileSerializer.cpp
@@ -103,7 +103,7 @@ bool cSchematicFileSerializer::SaveToSchematicFile(const cBlockArea & a_BlockAre
-AString cSchematicFileSerializer::SaveToSchematicString(const cBlockArea & a_BlockArea)
+bool cSchematicFileSerializer::SaveToSchematicString(const cBlockArea & a_BlockArea, AString & a_Out)
{
// Serialize into NBT data:
AString NBT = SaveToSchematicNBT(a_BlockArea);
@@ -114,14 +114,13 @@ AString cSchematicFileSerializer::SaveToSchematicString(const cBlockArea & a_Blo
}
// Gzip the data:
- AString Compressed;
- int res = CompressStringGZIP(NBT.data(), NBT.size(), Compressed);
+ int res = CompressStringGZIP(NBT.data(), NBT.size(), a_Out);
if (res != Z_OK)
{
LOG("%s: Cannot Gzip the area data NBT representation: %d", __FUNCTION__, res);
return false;
}
- return Compressed;
+ return true;
}
diff --git a/src/WorldStorage/SchematicFileSerializer.h b/src/WorldStorage/SchematicFileSerializer.h
index f6ce1c16c..05b6c74f4 100644
--- a/src/WorldStorage/SchematicFileSerializer.h
+++ b/src/WorldStorage/SchematicFileSerializer.h
@@ -36,8 +36,8 @@ public:
static bool SaveToSchematicFile(const cBlockArea & a_BlockArea, const AString & a_FileName);
/** Saves the area into a string containing the .schematic file data.
- Returns the data, or empty string if failed. */
- static AString SaveToSchematicString(const cBlockArea & a_BlockArea);
+ Returns true if successful, false on failure. The data is stored into a_Out. */
+ static bool SaveToSchematicString(const cBlockArea & a_BlockArea, AString & a_Out);
private:
/** Loads the area from a schematic file uncompressed and parsed into a NBT tree.
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[]
}