summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/BlockEntities/CommandBlockEntity.cpp14
-rw-r--r--src/Blocks/BlockCommandBlock.h32
-rw-r--r--src/Blocks/BlockHandler.cpp2
-rw-r--r--src/ClientHandle.cpp24
-rw-r--r--src/ClientHandle.h1
-rw-r--r--src/Protocol/Protocol.h1
-rw-r--r--src/Protocol/Protocol125.h1
-rw-r--r--src/Protocol/Protocol17x.cpp68
-rw-r--r--src/Protocol/Protocol17x.h2
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp10
-rw-r--r--src/Protocol/ProtocolRecognizer.h1
11 files changed, 151 insertions, 5 deletions
diff --git a/src/BlockEntities/CommandBlockEntity.cpp b/src/BlockEntities/CommandBlockEntity.cpp
index ca617b04d..7e9015d33 100644
--- a/src/BlockEntities/CommandBlockEntity.cpp
+++ b/src/BlockEntities/CommandBlockEntity.cpp
@@ -7,6 +7,7 @@
#include "json/json.h"
#include "CommandBlockEntity.h"
#include "../Entities/Player.h"
+#include "../WorldStorage/FastNBT.h"
#include "../CommandOutput.h"
#include "../Root.h"
@@ -40,6 +41,15 @@ void cCommandBlockEntity::UsedBy(cPlayer * a_Player)
void cCommandBlockEntity::SetCommand(const AString & a_Cmd)
{
m_Command = a_Cmd;
+
+ /*
+ Vanilla requires that the server send a Block Entity Update after a command has been set
+ Therefore, command blocks don't support on-the-fly (when window is open) updating of a command and therefore...
+ ...the following code can't be put in UsedBy just before the window opens
+
+ Just documenting my experience in getting this to work :P
+ */
+ m_World->BroadcastBlockEntity(GetPosX(), GetPosY(), GetPosZ());
}
@@ -48,6 +58,7 @@ void cCommandBlockEntity::SetCommand(const AString & a_Cmd)
void cCommandBlockEntity::SetLastOutput(const AString & a_LastOut)
{
+ m_World->BroadcastBlockEntity(GetPosX(), GetPosY(), GetPosZ());
m_LastOutput = a_LastOut;
}
@@ -131,8 +142,7 @@ bool cCommandBlockEntity::Tick(float a_Dt, cChunk & a_Chunk)
void cCommandBlockEntity::SendTo(cClientHandle & a_Client)
{
- // Nothing needs to be sent
- UNUSED(a_Client);
+ a_Client.SendUpdateBlockEntity(*this);
}
diff --git a/src/Blocks/BlockCommandBlock.h b/src/Blocks/BlockCommandBlock.h
new file mode 100644
index 000000000..cf0103765
--- /dev/null
+++ b/src/Blocks/BlockCommandBlock.h
@@ -0,0 +1,32 @@
+
+#pragma once
+
+#include "BlockEntity.h"
+
+
+
+
+
+class cBlockCommandBlockHandler :
+ public cBlockEntityHandler
+{
+public:
+ cBlockCommandBlockHandler(BLOCKTYPE a_BlockType)
+ : cBlockEntityHandler(a_BlockType)
+ {
+ }
+
+ virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
+ {
+ a_Pickups.push_back(cItem(E_BLOCK_AIR, 8, 0));
+ }
+
+ virtual const char * GetStepSound(void) override
+ {
+ return "step.stone";
+ }
+} ;
+
+
+
+
diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp
index ff1022e12..b9c0887ce 100644
--- a/src/Blocks/BlockHandler.cpp
+++ b/src/Blocks/BlockHandler.cpp
@@ -14,6 +14,7 @@
#include "BlockChest.h"
#include "BlockCloth.h"
#include "BlockCobWeb.h"
+#include "BlockCommandBlock.h"
#include "BlockComparator.h"
#include "BlockCrops.h"
#include "BlockDeadBush.h"
@@ -116,6 +117,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_CAULDRON: return new cBlockCauldronHandler (a_BlockType);
case E_BLOCK_CHEST: return new cBlockChestHandler (a_BlockType);
case E_BLOCK_COAL_ORE: return new cBlockOreHandler (a_BlockType);
+ case E_BLOCK_COMMAND_BLOCK: return new cBlockCommandBlockHandler (a_BlockType);
case E_BLOCK_ACTIVE_COMPARATOR: return new cBlockComparatorHandler (a_BlockType);
case E_BLOCK_COBBLESTONE: return new cBlockStoneHandler (a_BlockType);
case E_BLOCK_COBBLESTONE_STAIRS: return new cBlockStairsHandler (a_BlockType);
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index 1eec00bc3..74d192129 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -542,12 +542,18 @@ void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ,
void cClientHandle::HandlePluginMessage(const AString & a_Channel, const AString & a_Message)
{
- if (a_Channel == "MC|AdvCdm") // Command block
+ if (a_Channel == "MC|AdvCdm") // Command block, set text, Client -> Server
{
const char* Data = a_Message.c_str();
-
HandleCommandBlockMessage(Data, a_Message.size());
-
+ return;
+ }
+ else if (a_Channel == "MC|Brand") // Client <-> Server branding exchange
+ {
+ // We are custom,
+ // We are awesome,
+ // We are MCServer.
+ SendPluginMessage("MC|Brand", "MCServer");
return;
}
@@ -562,6 +568,7 @@ void cClientHandle::HandleCommandBlockMessage(const char* a_Data, unsigned int a
{
if (a_Length < 14)
{
+ SendChat(Printf("%s[INFO]%s Failure setting command block command; bad request", cChatColor::Red.c_str(), cChatColor::White.c_str()));
LOGD("Malformed MC|AdvCdm packet.");
return;
}
@@ -591,6 +598,7 @@ void cClientHandle::HandleCommandBlockMessage(const char* a_Data, unsigned int a
default:
{
+ SendChat(Printf("%s[INFO]%s Failure setting command block command; unhandled mode", cChatColor::Red.c_str(), cChatColor::White.c_str()));
LOGD("Unhandled MC|AdvCdm packet mode.");
return;
}
@@ -613,6 +621,8 @@ void cClientHandle::HandleCommandBlockMessage(const char* a_Data, unsigned int a
cWorld * World = m_Player->GetWorld();
World->DoWithCommandBlockAt(BlockX, BlockY, BlockZ, CmdBlockCB);
+
+ SendChat(Printf("%s[INFO]%s Successfully set command block command", cChatColor::Green.c_str(), cChatColor::White.c_str()));
}
@@ -2199,6 +2209,14 @@ void cClientHandle::SendUnloadChunk(int a_ChunkX, int a_ChunkZ)
+void cClientHandle::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
+{
+ m_Protocol->SendUpdateBlockEntity(a_BlockEntity);
+}
+
+
+
+
void cClientHandle::SendUpdateSign(
int a_BlockX, int a_BlockY, int a_BlockZ,
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index 373ca9e2e..4add022a6 100644
--- a/src/ClientHandle.h
+++ b/src/ClientHandle.h
@@ -136,6 +136,7 @@ public:
void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ);
void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay);
void SendUnloadChunk (int a_ChunkX, int a_ChunkZ);
+ void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity);
void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4);
void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ );
void SendWeather (eWeather a_Weather);
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index 3293da32c..1bc5d528e 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -103,6 +103,7 @@ public:
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) = 0;
virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay) = 0;
virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) = 0;
+ virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) = 0;
virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) = 0;
virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) = 0;
virtual void SendWeather (eWeather a_Weather) = 0;
diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h
index d0e5c9428..310f9dd78 100644
--- a/src/Protocol/Protocol125.h
+++ b/src/Protocol/Protocol125.h
@@ -79,6 +79,7 @@ public:
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay) override;
virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override;
+ virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override {};
virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override;
virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) override;
virtual void SendWeather (eWeather a_Weather) override;
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index 5b3a79555..293f96186 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -24,6 +24,7 @@ Implements the 1.7.x protocol classes:
#include "../Entities/Player.h"
#include "../Mobs/IncludeAllMonsters.h"
#include "../UI/Window.h"
+#include "../BlockEntities/CommandBlockEntity.h"
@@ -892,6 +893,28 @@ void cProtocol172::SendUnloadChunk(int a_ChunkX, int a_ChunkZ)
+void cProtocol172::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
+{
+ cPacketizer Pkt(*this, 0x35); // Update tile entity packet
+ Pkt.WriteInt(a_BlockEntity.GetPosX());
+ Pkt.WriteShort(a_BlockEntity.GetPosY());
+ Pkt.WriteInt(a_BlockEntity.GetPosZ());
+
+ Byte Action = 0;
+ switch (a_BlockEntity.GetBlockType())
+ {
+ 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
+ default: ASSERT(!"Unhandled or unimplemented BlockEntity update request!"); break;
+ }
+ Pkt.WriteByte(Action);
+
+ Pkt.WriteBlockEntity(a_BlockEntity);
+}
+
+
+
+
void cProtocol172::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4)
{
@@ -1819,6 +1842,51 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item)
+void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEntity)
+{
+ cFastNBTWriter Writer;
+
+ switch (a_BlockEntity.GetBlockType())
+ {
+ case E_BLOCK_COMMAND_BLOCK:
+ {
+ cCommandBlockEntity & CommandBlockEntity = (cCommandBlockEntity &)a_BlockEntity;
+
+ Writer.AddByte("TrackOutput", 1); // Neither I nor the MC wiki has any idea about this
+ Writer.AddInt("SuccessCount", CommandBlockEntity.GetResult());
+ Writer.AddInt("x", CommandBlockEntity.GetPosX());
+ Writer.AddInt("y", CommandBlockEntity.GetPosY());
+ Writer.AddInt("z", CommandBlockEntity.GetPosZ());
+ Writer.AddString("Command", CommandBlockEntity.GetCommand().c_str());
+ // You can set custom names for windows in Vanilla
+ // For a command block, this would be the 'name' prepended to anything it outputs into global chat
+ // MCS doesn't have this, so just leave it @ '@'. (geddit?)
+ Writer.AddString("CustomName", "@");
+ Writer.AddString("id", "Control"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
+
+ if (!CommandBlockEntity.GetLastOutput().empty())
+ {
+ AString Output;
+ Printf(Output, "{\"text\":\"%s\"}", CommandBlockEntity.GetLastOutput().c_str());
+
+ Writer.AddString("LastOutput", Output.c_str());
+ }
+ break;
+ }
+ default: break;
+ }
+
+ Writer.Finish();
+
+ AString Compressed;
+ CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed);
+ WriteShort(Compressed.size());
+ WriteBuf(Compressed.data(), Compressed.size());
+}
+
+
+
+
void cProtocol172::cPacketizer::WriteByteAngle(double a_Angle)
{
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index 07dba834b..3ae774c18 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -102,6 +102,7 @@ public:
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay) override;
virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override;
+ virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override;
virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override;
virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) override;
virtual void SendWeather (eWeather a_Weather) override;
@@ -189,6 +190,7 @@ protected:
void WriteEntityMetadata(const cEntity & a_Entity); // Writes the metadata for the specified entity, not including the terminating 0x7f
void WriteMobMetadata(const cMonster & a_Mob); // Writes the mob-specific metadata for the specified mob
void WriteEntityProperties(const cEntity & a_Entity); // Writes the entity properties for the specified entity, including the Count field
+ void WriteBlockEntity(const cBlockEntity & a_BlockEntity);
protected:
cProtocol172 & m_Protocol;
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index a21f4f042..5524af136 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -636,6 +636,16 @@ void cProtocolRecognizer::SendUnloadChunk(int a_ChunkX, int a_ChunkZ)
+void cProtocolRecognizer::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
+{
+ ASSERT(m_Protocol != NULL);
+ m_Protocol->SendUpdateBlockEntity(a_BlockEntity);
+}
+
+
+
+
+
void cProtocolRecognizer::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4)
{
ASSERT(m_Protocol != NULL);
diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h
index e94f4cde8..2dccace6e 100644
--- a/src/Protocol/ProtocolRecognizer.h
+++ b/src/Protocol/ProtocolRecognizer.h
@@ -114,6 +114,7 @@ public:
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay) override;
virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override;
+ virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override;
virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override;
virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) override;
virtual void SendWeather (eWeather a_Weather) override;