1
0
Fork 0

Improved command blocks

* Their command and previous output are displayed on the client
* They have a BlockHandler implementation, so you can't place blocks on
them anymore
+ As a side effect, implemented UpdateBlockEntity
This commit is contained in:
Tiger Wang 2014-01-19 00:54:38 +00:00
parent 36b9d42819
commit f8c8dcc7f3
11 changed files with 124 additions and 5 deletions

View File

@ -7,10 +7,11 @@
#include "json/json.h"
#include "CommandBlockEntity.h"
#include "../Entities/Player.h"
#include "../WorldStorage/FastNBT.h"
#include "CommandOutput.h"
#include "Root.h"
#include "Server.h" // ExecuteConsoleCommand()
#include "../CommandOutput.h"
#include "../Root.h"
#include "../Server.h" // ExecuteConsoleCommand()
@ -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());
}
@ -131,8 +141,30 @@ bool cCommandBlockEntity::Tick(float a_Dt, cChunk & a_Chunk)
void cCommandBlockEntity::SendTo(cClientHandle & a_Client)
{
// Nothing needs to be sent
UNUSED(a_Client);
cFastNBTWriter Writer;
Writer.AddByte("TrackOutput", 1); // Neither I nor the MC wiki has any idea about this
Writer.AddInt("SuccessCount", GetResult());
Writer.AddInt("x", GetPosX());
Writer.AddInt("y", GetPosY());
Writer.AddInt("z", GetPosZ());
Writer.AddString("Command", 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 (!GetLastOutput().empty())
{
AString Output;
Printf(Output, "{\"text\":\"%s\"}", GetLastOutput().c_str());
Writer.AddString("LastOutput", Output.c_str());
}
Writer.Finish();
a_Client.SendUpdateBlockEntity(GetPosX(), GetPosY(), GetPosZ(), 2, Writer);
}

View File

@ -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";
}
} ;

View File

@ -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);

View File

@ -20,6 +20,7 @@
#include "Items/ItemHandler.h"
#include "Blocks/BlockHandler.h"
#include "Blocks/BlockSlab.h"
#include "WorldStorage/FastNBT.h"
#include "Vector3f.h"
#include "Vector3d.h"
@ -2203,6 +2204,14 @@ void cClientHandle::SendUnloadChunk(int a_ChunkX, int a_ChunkZ)
void cClientHandle::SendUpdateBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, Byte a_Action, cFastNBTWriter & a_NBT)
{
m_Protocol->SendUpdateBlockEntity(a_BlockX, a_BlockY, a_BlockZ, a_Action, a_NBT);
}
void cClientHandle::SendUpdateSign(
int a_BlockX, int a_BlockY, int a_BlockZ,

View File

@ -16,6 +16,7 @@
#include "OSSupport/SocketThreads.h"
#include "ChunkDef.h"
#include "ByteBuffer.h"
#include "WorldStorage/FastNBT.h"
@ -136,6 +137,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 (int a_BlockX, int a_BlockY, int a_BlockZ, Byte a_Action, cFastNBTWriter & a_NBT);
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);

View File

@ -12,6 +12,7 @@
#include "../Defines.h"
#include "../Endianness.h"
#include "../WorldStorage/FastNBT.h"
@ -103,6 +104,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 (int a_BlockX, int a_BlockY, int a_BlockZ, Byte a_Action, cFastNBTWriter & a_NBT) = 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;

View File

@ -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 (int a_BlockX, int a_BlockY, int a_BlockZ, Byte a_Action, cFastNBTWriter & a_NBT) 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;

View File

@ -892,6 +892,20 @@ void cProtocol172::SendUnloadChunk(int a_ChunkX, int a_ChunkZ)
void cProtocol172::SendUpdateBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, Byte a_Action, cFastNBTWriter & a_NBT)
{
cPacketizer Pkt(*this, 0x35); // Update tile entity packet
Pkt.WriteInt(a_BlockX);
Pkt.WriteShort(a_BlockY);
Pkt.WriteInt(a_BlockZ);
Pkt.WriteByte(a_Action);
Pkt.WriteBlockEntity(a_NBT);
}
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 +1833,17 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item)
void cProtocol172::cPacketizer::WriteBlockEntity(const cFastNBTWriter & a_NBT)
{
AString Compressed;
CompressStringGZIP(a_NBT.GetResult().data(), a_NBT.GetResult().size(), Compressed);
WriteShort(Compressed.size());
WriteBuf(Compressed.data(), Compressed.size());
}
void cProtocol172::cPacketizer::WriteByteAngle(double a_Angle)
{

View File

@ -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 (int a_BlockX, int a_BlockY, int a_BlockZ, Byte a_Action, cFastNBTWriter & a_NBT) 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 cFastNBTWriter & a_NBT);
protected:
cProtocol172 & m_Protocol;

View File

@ -636,6 +636,16 @@ void cProtocolRecognizer::SendUnloadChunk(int a_ChunkX, int a_ChunkZ)
void cProtocolRecognizer::SendUpdateBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, Byte a_Action, cFastNBTWriter & a_NBT)
{
ASSERT(m_Protocol != NULL);
m_Protocol->SendUpdateBlockEntity(a_BlockX, a_BlockY, a_BlockZ, a_Action, a_NBT);
}
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);

View File

@ -12,6 +12,7 @@
#include "Protocol.h"
#include "../ByteBuffer.h"
#include "../WorldStorage/FastNBT.h"
@ -114,6 +115,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 (int a_BlockX, int a_BlockY, int a_BlockZ, Byte a_Action, cFastNBTWriter & a_NBT) 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;