summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTORS1
-rw-r--r--src/BlockEntities/BlockEntity.cpp24
-rw-r--r--src/BlockEntities/CommandBlockEntity.cpp173
-rw-r--r--src/BlockEntities/CommandBlockEntity.h85
-rw-r--r--src/Chunk.cpp34
-rw-r--r--src/Chunk.h16
-rw-r--r--src/ChunkMap.cpp17
-rw-r--r--src/ChunkMap.h23
-rw-r--r--src/Simulator/RedstoneSimulator.cpp27
-rw-r--r--src/Simulator/RedstoneSimulator.h4
-rw-r--r--src/World.cpp9
-rw-r--r--src/World.h16
12 files changed, 396 insertions, 33 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 150bcf09e..b15a36a38 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -20,5 +20,6 @@ worktycho
Sxw1212
tonibm19
Diusrex
+structinf (xdot)
Please add yourself to this list if you contribute to MCServer.
diff --git a/src/BlockEntities/BlockEntity.cpp b/src/BlockEntities/BlockEntity.cpp
index 5d7e4a37a..97b5c1a66 100644
--- a/src/BlockEntities/BlockEntity.cpp
+++ b/src/BlockEntities/BlockEntity.cpp
@@ -6,6 +6,7 @@
#include "Globals.h"
#include "BlockEntity.h"
#include "ChestEntity.h"
+#include "CommandBlockEntity.h"
#include "DispenserEntity.h"
#include "DropperEntity.h"
#include "EnderChestEntity.h"
@@ -23,17 +24,18 @@ cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE
{
switch (a_BlockType)
{
- case E_BLOCK_CHEST: return new cChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
- 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_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);
- case E_BLOCK_HOPPER: return new cHopperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
- case E_BLOCK_SIGN_POST: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
- case E_BLOCK_WALLSIGN: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
- case E_BLOCK_NOTE_BLOCK: return new cNoteEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
- case E_BLOCK_JUKEBOX: return new cJukeboxEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
+ case E_BLOCK_CHEST: return new cChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
+ case E_BLOCK_COMMAND_BLOCK: return new cCommandBlockEntity(a_BlockX, a_BlockY, a_BlockZ, a_World);
+ 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_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);
+ case E_BLOCK_HOPPER: return new cHopperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
+ case E_BLOCK_SIGN_POST: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
+ case E_BLOCK_WALLSIGN: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
+ case E_BLOCK_NOTE_BLOCK: return new cNoteEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
+ case E_BLOCK_JUKEBOX: return new cJukeboxEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
}
LOGD("%s: Requesting creation of an unknown block entity - block type %d (%s)",
__FUNCTION__, a_BlockType, ItemTypeToString(a_BlockType).c_str()
diff --git a/src/BlockEntities/CommandBlockEntity.cpp b/src/BlockEntities/CommandBlockEntity.cpp
new file mode 100644
index 000000000..6e371e0fe
--- /dev/null
+++ b/src/BlockEntities/CommandBlockEntity.cpp
@@ -0,0 +1,173 @@
+
+// CommandBlockEntity.cpp
+
+// Implements the cCommandBlockEntity class representing a single command block in the world
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+#include "json/json.h"
+#include "CommandBlockEntity.h"
+#include "../Entities/Player.h"
+
+
+
+
+
+cCommandBlockEntity::cCommandBlockEntity(int a_X, int a_Y, int a_Z, cWorld * a_World) :
+ super(E_BLOCK_COMMAND_BLOCK, a_X, a_Y, a_Z, a_World),
+ m_ShouldExecute(false),
+ m_IsPowered(false)
+{
+ SetBlockEntity(this); // cBlockEntityWindowOwner
+}
+
+
+
+
+
+
+cCommandBlockEntity::~cCommandBlockEntity()
+{
+ // Tell window its owner is destroyed
+ cWindow * Window = GetWindow();
+ if (Window != NULL)
+ {
+ Window->OwnerDestroyed();
+ }
+}
+
+
+
+
+
+
+void cCommandBlockEntity::UsedBy(cPlayer * a_Player)
+{
+ cWindow * Window = GetWindow();
+ if (Window == NULL)
+ {
+ //OpenWindow(new cDropSpenserWindow(m_PosX, m_PosY, m_PosZ, this));
+ Window = GetWindow();
+ }
+
+ if (Window != NULL)
+ {
+ if (a_Player->GetWindow() != Window)
+ {
+ a_Player->OpenWindow(Window);
+ }
+ }
+}
+
+
+
+
+
+void cCommandBlockEntity::SetCommand(const AString & a_Cmd)
+{
+ m_Command = a_Cmd;LOGD("Hrey %s", a_Cmd.c_str());
+}
+
+
+
+
+
+const AString & cCommandBlockEntity::GetCommand(void) const
+{
+ return m_Command;
+}
+
+
+
+
+
+const AString & cCommandBlockEntity::GetLastOutput(void) const
+{
+ return m_LastOutput;
+}
+
+
+
+
+
+void cCommandBlockEntity::Activate(void)
+{
+ m_ShouldExecute = true;
+}
+
+
+
+
+
+void cCommandBlockEntity::SetRedstonePower(bool a_IsPowered)
+{
+ if (a_IsPowered && !m_IsPowered)
+ {
+ Activate();
+ }
+ m_IsPowered = a_IsPowered;
+}
+
+
+
+
+
+bool cCommandBlockEntity::Tick(float a_Dt, cChunk & a_Chunk)
+{
+ if (!m_ShouldExecute)
+ {
+ return false;
+ }
+
+ m_ShouldExecute = false;
+ Execute();
+ return true;
+}
+
+
+
+
+
+void cCommandBlockEntity::SendTo(cClientHandle & a_Client)
+{
+ // Nothing needs to be sent
+ UNUSED(a_Client);
+}
+
+
+
+
+
+bool cCommandBlockEntity::LoadFromJson(const Json::Value & a_Value)
+{
+ m_Command = a_Value.get("Command", "").asString();
+
+ m_LastOutput = a_Value.get("LastOutput", "").asString();
+
+ return true;
+}
+
+
+
+
+
+void cCommandBlockEntity::SaveToJson(Json::Value & a_Value)
+{
+ a_Value["Command"] = m_Command;
+
+ a_Value["LastOutput"] = m_LastOutput;
+}
+
+
+
+
+
+void cCommandBlockEntity::Execute()
+{
+ // TODO: Parse arguments and dispatch command
+ LOGD("Command: %s", m_Command.c_str());
+ m_LastOutput = "";
+}
+
+
+
+
diff --git a/src/BlockEntities/CommandBlockEntity.h b/src/BlockEntities/CommandBlockEntity.h
new file mode 100644
index 000000000..266a3c33d
--- /dev/null
+++ b/src/BlockEntities/CommandBlockEntity.h
@@ -0,0 +1,85 @@
+
+// CommandBlockEntity.h
+
+// Declares the cCommandBlockEntity class representing a single command block in the world
+
+
+
+
+
+#pragma once
+
+#include "BlockEntityWithItems.h"
+#include "../UI/WindowOwner.h"
+
+
+
+
+
+namespace Json
+{
+ class Value;
+}
+
+
+
+
+
+// tolua_begin
+
+class cCommandBlockEntity :
+ public cBlockEntity,
+ public cBlockEntityWindowOwner
+{
+ typedef cBlockEntity super;
+
+public:
+
+ // tolua_end
+
+ /// Creates a new empty command block entity
+ cCommandBlockEntity(int a_X, int a_Y, int a_Z, cWorld * a_World);
+ virtual ~cCommandBlockEntity();
+
+ bool LoadFromJson( const Json::Value& a_Value );
+ virtual void SaveToJson(Json::Value& a_Value ) override;
+
+ virtual bool Tick(float a_Dt, cChunk & a_Chunk) override;
+ virtual void SendTo(cClientHandle & a_Client) override;
+ virtual void UsedBy(cPlayer * a_Player) override;
+
+ // tolua_begin
+
+ /// Sets the internal redstone power flag to "on" or "off", depending on the parameter. Calls Activate() if appropriate
+ void SetRedstonePower(bool a_IsPowered);
+
+ /// Sets the command block to execute a command in the next tick
+ void Activate(void);
+
+ /// Sets the command
+ void SetCommand(const AString & a_Cmd);
+
+ /// Retrieves stored command
+ const AString & GetCommand(void) const;
+
+ /// Retrieves the last line of output generated by the command block
+ const AString & GetLastOutput(void) const;
+
+ // tolua_end
+
+private:
+
+ /// Executes the associated command
+ void Execute();
+
+ bool m_ShouldExecute;
+ bool m_IsPowered;
+
+ AString m_Command;
+
+ AString m_LastOutput;
+} ; // tolua_export
+
+
+
+
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index 0735c8144..a72464ec3 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -1298,6 +1298,7 @@ void cChunk::CreateBlockEntities(void)
switch (BlockType)
{
case E_BLOCK_CHEST:
+ case E_BLOCK_COMMAND_BLOCK:
case E_BLOCK_DISPENSER:
case E_BLOCK_DROPPER:
case E_BLOCK_ENDER_CHEST:
@@ -1425,6 +1426,7 @@ void cChunk::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType,
switch (a_BlockType)
{
case E_BLOCK_CHEST:
+ case E_BLOCK_COMMAND_BLOCK:
case E_BLOCK_DISPENSER:
case E_BLOCK_DROPPER:
case E_BLOCK_ENDER_CHEST:
@@ -2268,6 +2270,38 @@ bool cChunk::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBl
+bool cChunk::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & 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_COMMAND_BLOCK)
+ {
+ // There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
+ return false;
+ }
+
+ // The correct block entity is here,
+ if (a_Callback.Item((cCommandBlockEntity *)*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 f0a50c3c4..4ac38c46c 100644
--- a/src/Chunk.h
+++ b/src/Chunk.h
@@ -40,12 +40,13 @@ class cFluidSimulatorData;
class cMobCensus;
class cMobSpawner;
-typedef std::list<cClientHandle *> cClientHandleList;
-typedef cItemCallback<cEntity> cEntityCallback;
-typedef cItemCallback<cChestEntity> cChestCallback;
-typedef cItemCallback<cDispenserEntity> cDispenserCallback;
-typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
-typedef cItemCallback<cNoteEntity> cNoteBlockCallback;
+typedef std::list<cClientHandle *> cClientHandleList;
+typedef cItemCallback<cEntity> cEntityCallback;
+typedef cItemCallback<cChestEntity> cChestCallback;
+typedef cItemCallback<cDispenserEntity> cDispenserCallback;
+typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
+typedef cItemCallback<cNoteEntity> cNoteBlockCallback;
+typedef cItemCallback<cCommandBlockEntity> cCommandBlockCallback;
@@ -237,6 +238,9 @@ public:
/// Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found
bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback);
+ /// 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);
+
/// 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 e14090b18..5797eb453 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -1968,6 +1968,23 @@ bool cChunkMap::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNot
+bool cChunkMap::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & 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->DoWithCommandBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
+}
+
+
+
+
bool cChunkMap::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4)
{
diff --git a/src/ChunkMap.h b/src/ChunkMap.h
index e688d1f93..e9d8ee30b 100644
--- a/src/ChunkMap.h
+++ b/src/ChunkMap.h
@@ -23,6 +23,7 @@ class cDropperEntity;
class cDropSpenserEntity;
class cFurnaceEntity;
class cNoteEntity;
+class cCommandBlockEntity;
class cPawn;
class cPickup;
class cChunkDataSerializer;
@@ -32,15 +33,16 @@ class cMobSpawner;
typedef std::list<cClientHandle *> cClientHandleList;
typedef cChunk * cChunkPtr;
-typedef cItemCallback<cEntity> cEntityCallback;
-typedef cItemCallback<cBlockEntity> cBlockEntityCallback;
-typedef cItemCallback<cChestEntity> cChestCallback;
-typedef cItemCallback<cDispenserEntity> cDispenserCallback;
-typedef cItemCallback<cDropperEntity> cDropperCallback;
-typedef cItemCallback<cDropSpenserEntity> cDropSpenserCallback;
-typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
-typedef cItemCallback<cNoteEntity> cNoteBlockCallback;
-typedef cItemCallback<cChunk> cChunkCallback;
+typedef cItemCallback<cEntity> cEntityCallback;
+typedef cItemCallback<cBlockEntity> cBlockEntityCallback;
+typedef cItemCallback<cChestEntity> cChestCallback;
+typedef cItemCallback<cDispenserEntity> cDispenserCallback;
+typedef cItemCallback<cDropperEntity> cDropperCallback;
+typedef cItemCallback<cDropSpenserEntity> cDropSpenserCallback;
+typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
+typedef cItemCallback<cNoteEntity> cNoteBlockCallback;
+typedef cItemCallback<cCommandBlockEntity> cCommandBlockCallback;
+typedef cItemCallback<cChunk> cChunkCallback;
@@ -236,6 +238,9 @@ public:
/// Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found
bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback); // Lua-accessible
+ /// 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); // Lua-accessible
+
/// Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coords, true if found
bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // Lua-accessible
diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp
index 469680098..e361cbf49 100644
--- a/src/Simulator/RedstoneSimulator.cpp
+++ b/src/Simulator/RedstoneSimulator.cpp
@@ -4,6 +4,7 @@
#include "RedstoneSimulator.h"
#include "../BlockEntities/DropSpenserEntity.h"
#include "../BlockEntities/NoteEntity.h"
+#include "../BlockEntities/CommandBlockEntity.h"
#include "../Entities/TNTEntity.h"
#include "../Blocks/BlockTorch.h"
#include "../Blocks/BlockDoor.h"
@@ -215,11 +216,12 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
{
case E_BLOCK_BLOCK_OF_REDSTONE: HandleRedstoneBlock(a_X, dataitr->y, a_Z); break;
case E_BLOCK_LEVER: HandleRedstoneLever(a_X, dataitr->y, a_Z); break;
- case E_BLOCK_TNT: HandleTNT(a_X, dataitr->y, a_Z); break;
+ case E_BLOCK_TNT: HandleTNT(a_X, dataitr->y, a_Z); break;
case E_BLOCK_TRAPDOOR: HandleTrapdoor(a_X, dataitr->y, a_Z); break;
case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(a_X, dataitr->y, a_Z); break;
case E_BLOCK_NOTE_BLOCK: HandleNoteBlock(a_X, dataitr->y, a_Z); break;
case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(a_X, dataitr->y, a_Z); break;
+ case E_BLOCK_COMMAND_BLOCK: HandleCommandBlock(a_X, dataitr->y, a_Z); break;
case E_BLOCK_REDSTONE_TORCH_OFF:
case E_BLOCK_REDSTONE_TORCH_ON:
@@ -763,6 +765,29 @@ void cRedstoneSimulator::HandleDoor(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cRedstoneSimulator::HandleCommandBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
+{
+ class cSetPowerToCommandBlock :
+ public cCommandBlockCallback
+ {
+ bool m_IsPowered;
+ public:
+ cSetPowerToCommandBlock(bool a_IsPowered) : m_IsPowered(a_IsPowered) {}
+
+ virtual bool Item(cCommandBlockEntity * a_CommandBlock) override
+ {
+ a_CommandBlock->SetRedstonePower(m_IsPowered);
+ return false;
+ }
+ } CmdBlockSP (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ));
+
+ m_World.DoWithCommandBlockAt(a_BlockX, a_BlockY, a_BlockZ, CmdBlockSP);
+}
+
+
+
+
+
void cRedstoneSimulator::HandleRail(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType)
{
switch (a_MyType)
diff --git a/src/Simulator/RedstoneSimulator.h b/src/Simulator/RedstoneSimulator.h
index 63a5be3d3..bb2efeb8a 100644
--- a/src/Simulator/RedstoneSimulator.h
+++ b/src/Simulator/RedstoneSimulator.h
@@ -110,6 +110,8 @@ private:
void HandleRedstoneLamp(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState);
/** Handles doords */
void HandleDoor(int a_BlockX, int a_BlockY, int a_BlockZ);
+ /** Handles command blocks */
+ void HandleCommandBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
/** Handles activator, detector, and powered rails */
void HandleRail(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType);
/** Handles trapdoors */
@@ -166,6 +168,7 @@ private:
switch (Block)
{
case E_BLOCK_ACTIVATOR_RAIL:
+ case E_BLOCK_COMMAND_BLOCK:
case E_BLOCK_PISTON:
case E_BLOCK_STICKY_PISTON:
case E_BLOCK_DISPENSER:
@@ -220,6 +223,7 @@ private:
case E_BLOCK_ACTIVATOR_RAIL:
case E_BLOCK_ACTIVE_COMPARATOR:
case E_BLOCK_BLOCK_OF_REDSTONE:
+ case E_BLOCK_COMMAND_BLOCK:
case E_BLOCK_DETECTOR_RAIL:
case E_BLOCK_DISPENSER:
case E_BLOCK_DAYLIGHT_SENSOR:
diff --git a/src/World.cpp b/src/World.cpp
index 3e7c0ef74..7c56d2efb 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -1149,6 +1149,15 @@ bool cWorld::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBl
+bool cWorld::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback)
+{
+ return m_ChunkMap->DoWithCommandBlockAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
+}
+
+
+
+
+
bool cWorld::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4)
{
return m_ChunkMap->GetSignLines(a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4);
diff --git a/src/World.h b/src/World.h
index ef74a65c7..c410e658e 100644
--- a/src/World.h
+++ b/src/World.h
@@ -46,12 +46,13 @@ class cMobCensus;
typedef std::list< cPlayer * > cPlayerList;
-typedef cItemCallback<cPlayer> cPlayerListCallback;
-typedef cItemCallback<cEntity> cEntityCallback;
-typedef cItemCallback<cChestEntity> cChestCallback;
-typedef cItemCallback<cDispenserEntity> cDispenserCallback;
-typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
-typedef cItemCallback<cNoteEntity> cNoteBlockCallback;
+typedef cItemCallback<cPlayer> cPlayerListCallback;
+typedef cItemCallback<cEntity> cEntityCallback;
+typedef cItemCallback<cChestEntity> cChestCallback;
+typedef cItemCallback<cDispenserEntity> cDispenserCallback;
+typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
+typedef cItemCallback<cNoteEntity> cNoteBlockCallback;
+typedef cItemCallback<cCommandBlockEntity> cCommandBlockCallback;
@@ -466,6 +467,9 @@ public:
/// Calls the callback for the noteblock at the specified coords; returns false if there's no noteblock at those coords or callback returns true, returns true if found
bool DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback & a_Callback); // Exported in ManualBindings.cpp
+
+ /// 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); // TODO: Export
/// 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