From 9a9b51a5134d8afd8f089d247c59668bd7da695d Mon Sep 17 00:00:00 2001 From: andrew Date: Sat, 18 Jan 2014 15:16:47 +0200 Subject: Basic command block implementation --- src/BlockEntities/BlockEntity.cpp | 24 +++-- src/BlockEntities/CommandBlockEntity.cpp | 173 +++++++++++++++++++++++++++++++ src/BlockEntities/CommandBlockEntity.h | 85 +++++++++++++++ src/Chunk.cpp | 34 ++++++ src/Chunk.h | 16 +-- src/ChunkMap.cpp | 17 +++ src/ChunkMap.h | 23 ++-- src/Simulator/RedstoneSimulator.cpp | 27 ++++- src/Simulator/RedstoneSimulator.h | 4 + src/World.cpp | 9 ++ src/World.h | 16 +-- 11 files changed, 395 insertions(+), 33 deletions(-) create mode 100644 src/BlockEntities/CommandBlockEntity.cpp create mode 100644 src/BlockEntities/CommandBlockEntity.h (limited to 'src') 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 cClientHandleList; -typedef cItemCallback cEntityCallback; -typedef cItemCallback cChestCallback; -typedef cItemCallback cDispenserCallback; -typedef cItemCallback cFurnaceCallback; -typedef cItemCallback cNoteBlockCallback; +typedef std::list cClientHandleList; +typedef cItemCallback cEntityCallback; +typedef cItemCallback cChestCallback; +typedef cItemCallback cDispenserCallback; +typedef cItemCallback cFurnaceCallback; +typedef cItemCallback cNoteBlockCallback; +typedef cItemCallback 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 cClientHandleList; typedef cChunk * cChunkPtr; -typedef cItemCallback cEntityCallback; -typedef cItemCallback cBlockEntityCallback; -typedef cItemCallback cChestCallback; -typedef cItemCallback cDispenserCallback; -typedef cItemCallback cDropperCallback; -typedef cItemCallback cDropSpenserCallback; -typedef cItemCallback cFurnaceCallback; -typedef cItemCallback cNoteBlockCallback; -typedef cItemCallback cChunkCallback; +typedef cItemCallback cEntityCallback; +typedef cItemCallback cBlockEntityCallback; +typedef cItemCallback cChestCallback; +typedef cItemCallback cDispenserCallback; +typedef cItemCallback cDropperCallback; +typedef cItemCallback cDropSpenserCallback; +typedef cItemCallback cFurnaceCallback; +typedef cItemCallback cNoteBlockCallback; +typedef cItemCallback cCommandBlockCallback; +typedef cItemCallback 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 cPlayerListCallback; -typedef cItemCallback cEntityCallback; -typedef cItemCallback cChestCallback; -typedef cItemCallback cDispenserCallback; -typedef cItemCallback cFurnaceCallback; -typedef cItemCallback cNoteBlockCallback; +typedef cItemCallback cPlayerListCallback; +typedef cItemCallback cEntityCallback; +typedef cItemCallback cChestCallback; +typedef cItemCallback cDispenserCallback; +typedef cItemCallback cFurnaceCallback; +typedef cItemCallback cNoteBlockCallback; +typedef cItemCallback 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 -- cgit v1.2.3 From be5299350a3b808ade39df7e9654eda47732e96e Mon Sep 17 00:00:00 2001 From: andrew Date: Sat, 18 Jan 2014 15:40:47 +0200 Subject: Command block (de)serialization --- src/BlockEntities/CommandBlockEntity.cpp | 32 +++++++++++++++++++++++- src/BlockEntities/CommandBlockEntity.h | 13 ++++++++-- src/WorldStorage/NBTChunkSerializer.cpp | 37 ++++++++++++++++++++-------- src/WorldStorage/NBTChunkSerializer.h | 2 ++ src/WorldStorage/WSSAnvil.cpp | 42 ++++++++++++++++++++++++++++++++ src/WorldStorage/WSSAnvil.h | 17 +++++++------ 6 files changed, 122 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/BlockEntities/CommandBlockEntity.cpp b/src/BlockEntities/CommandBlockEntity.cpp index 6e371e0fe..88e55dece 100644 --- a/src/BlockEntities/CommandBlockEntity.cpp +++ b/src/BlockEntities/CommandBlockEntity.cpp @@ -45,7 +45,7 @@ void cCommandBlockEntity::UsedBy(cPlayer * a_Player) cWindow * Window = GetWindow(); if (Window == NULL) { - //OpenWindow(new cDropSpenserWindow(m_PosX, m_PosY, m_PosZ, this)); + //OpenWindow(new cDropSpenserWindow(m_PosX, m_PosY, m_PosZ, this)); FIXME Window = GetWindow(); } @@ -71,6 +71,24 @@ void cCommandBlockEntity::SetCommand(const AString & a_Cmd) +void cCommandBlockEntity::SetLastOutput(const AString & a_LastOut) +{ + m_LastOutput = a_LastOut; +} + + + + + +void cCommandBlockEntity::SetResult(const NIBBLETYPE a_Result) +{ + m_Result = a_Result; +} + + + + + const AString & cCommandBlockEntity::GetCommand(void) const { return m_Command; @@ -89,6 +107,15 @@ const AString & cCommandBlockEntity::GetLastOutput(void) const +NIBBLETYPE cCommandBlockEntity::GetResult(void) const +{ + return m_Result; +} + + + + + void cCommandBlockEntity::Activate(void) { m_ShouldExecute = true; @@ -164,8 +191,11 @@ void cCommandBlockEntity::SaveToJson(Json::Value & a_Value) void cCommandBlockEntity::Execute() { // TODO: Parse arguments and dispatch command + LOGD("Command: %s", m_Command.c_str()); + m_LastOutput = ""; + m_Result = 0; } diff --git a/src/BlockEntities/CommandBlockEntity.h b/src/BlockEntities/CommandBlockEntity.h index 266a3c33d..c4529a1e6 100644 --- a/src/BlockEntities/CommandBlockEntity.h +++ b/src/BlockEntities/CommandBlockEntity.h @@ -48,6 +48,10 @@ public: virtual void SendTo(cClientHandle & a_Client) override; virtual void UsedBy(cPlayer * a_Player) override; + void SetLastOutput(const AString & a_LastOut); + + void SetResult(const NIBBLETYPE a_Result); + // tolua_begin /// Sets the internal redstone power flag to "on" or "off", depending on the parameter. Calls Activate() if appropriate @@ -64,6 +68,9 @@ public: /// Retrieves the last line of output generated by the command block const AString & GetLastOutput(void) const; + + /// Retrieves the result (signal strength) of the last operation + NIBBLETYPE GetResult(void) const; // tolua_end @@ -75,9 +82,11 @@ private: bool m_ShouldExecute; bool m_IsPowered; - AString m_Command; + AString m_Command; + + AString m_LastOutput; - AString m_LastOutput; + NIBBLETYPE m_Result; } ; // tolua_export diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index e1205f2be..b5b5e555b 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -10,6 +10,7 @@ #include "FastNBT.h" #include "../BlockEntities/ChestEntity.h" +#include "../BlockEntities/CommandBlockEntity.h" #include "../BlockEntities/DispenserEntity.h" #include "../BlockEntities/DropperEntity.h" #include "../BlockEntities/FurnaceEntity.h" @@ -219,8 +220,23 @@ void cNBTChunkSerializer::AddJukeboxEntity(cJukeboxEntity * a_Jukebox) void cNBTChunkSerializer::AddNoteEntity(cNoteEntity * a_Note) { m_Writer.BeginCompound(""); - AddBasicTileEntity(a_Note, "Music"); - m_Writer.AddByte("note", a_Note->GetPitch()); + AddBasicTileEntity(a_Note, "Music"); + m_Writer.AddByte("note", a_Note->GetPitch()); + m_Writer.EndCompound(); +} + + + + + +void cNBTChunkSerializer::AddCommandBlockEntity(cCommandBlockEntity * a_CmdBlock) +{ + m_Writer.BeginCompound(""); + AddBasicTileEntity(a_CmdBlock, "Control"); + m_Writer.AddString("Command", a_CmdBlock->GetCommand()); + m_Writer.AddInt ("SuccessCount", a_CmdBlock->GetResult()); + m_Writer.AddString("LastOutput", a_CmdBlock->GetLastOutput()); + m_Writer.AddByte ("TrackOutput", 1); // Unknown (?) m_Writer.EndCompound(); } @@ -639,15 +655,16 @@ void cNBTChunkSerializer::BlockEntity(cBlockEntity * a_Entity) // Add tile-entity into NBT: switch (a_Entity->GetBlockType()) { - 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_FURNACE: AddFurnaceEntity ((cFurnaceEntity *) a_Entity); break; - case E_BLOCK_HOPPER: AddHopperEntity ((cHopperEntity *) a_Entity); break; + 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_FURNACE: AddFurnaceEntity ((cFurnaceEntity *) a_Entity); break; + case E_BLOCK_HOPPER: AddHopperEntity ((cHopperEntity *) a_Entity); break; case E_BLOCK_SIGN_POST: - case E_BLOCK_WALLSIGN: AddSignEntity ((cSignEntity *) a_Entity); break; - case E_BLOCK_NOTE_BLOCK: AddNoteEntity ((cNoteEntity *) a_Entity); break; - case E_BLOCK_JUKEBOX: AddJukeboxEntity ((cJukeboxEntity *) a_Entity); break; + case E_BLOCK_WALLSIGN: AddSignEntity ((cSignEntity *) a_Entity); break; + case E_BLOCK_NOTE_BLOCK: AddNoteEntity ((cNoteEntity *) a_Entity); break; + case E_BLOCK_JUKEBOX: AddJukeboxEntity ((cJukeboxEntity *) a_Entity); break; + case E_BLOCK_COMMAND_BLOCK: AddCommandBlockEntity((cCommandBlockEntity *) a_Entity); break; default: { ASSERT(!"Unhandled block entity saved into Anvil"); diff --git a/src/WorldStorage/NBTChunkSerializer.h b/src/WorldStorage/NBTChunkSerializer.h index 9d4ac208c..245b68063 100644 --- a/src/WorldStorage/NBTChunkSerializer.h +++ b/src/WorldStorage/NBTChunkSerializer.h @@ -21,6 +21,7 @@ class cEntity; class cBlockEntity; class cBoat; class cChestEntity; +class cCommandBlockEntity; class cDispenserEntity; class cDropperEntity; class cFurnaceEntity; @@ -92,6 +93,7 @@ protected: void AddJukeboxEntity (cJukeboxEntity * a_Jukebox); void AddNoteEntity (cNoteEntity * a_Note); void AddSignEntity (cSignEntity * a_Sign); + void AddCommandBlockEntity(cCommandBlockEntity * a_CmdBlock); // Entities: void AddBasicEntity (cEntity * a_Entity, const AString & a_ClassName); diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 16513cd1b..85821fa51 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -15,6 +15,7 @@ #include "../StringCompression.h" #include "../BlockEntities/ChestEntity.h" +#include "../BlockEntities/CommandBlockEntity.h" #include "../BlockEntities/DispenserEntity.h" #include "../BlockEntities/DropperEntity.h" #include "../BlockEntities/FurnaceEntity.h" @@ -567,6 +568,10 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con { LoadChestFromNBT(a_BlockEntities, a_NBT, Child); } + else if (strncmp(a_NBT.GetData(sID), "Control", a_NBT.GetDataLength(sID)) == 0) + { + LoadCommandBlockFromNBT(a_BlockEntities, a_NBT, Child); + } else if (strncmp(a_NBT.GetData(sID), "Dropper", a_NBT.GetDataLength(sID)) == 0) { LoadDropperFromNBT(a_BlockEntities, a_NBT, Child); @@ -915,6 +920,43 @@ void cWSSAnvil::LoadSignFromNBT(cBlockEntityList & a_BlockEntities, const cParse +void cWSSAnvil::LoadCommandBlockFromNBT(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 CmdBlock(new cCommandBlockEntity(x, y, z, m_World)); + + int currentLine = a_NBT.FindChildByName(a_TagIdx, "Command"); + if (currentLine >= 0) + { + CmdBlock->SetCommand(a_NBT.GetString(currentLine)); + } + + currentLine = a_NBT.FindChildByName(a_TagIdx, "SuccessCount"); + if (currentLine >= 0) + { + CmdBlock->SetResult(a_NBT.GetInt(currentLine)); + } + + currentLine = a_NBT.FindChildByName(a_TagIdx, "LastOutput"); + if (currentLine >= 0) + { + CmdBlock->SetLastOutput(a_NBT.GetString(currentLine)); + } + + // FIXME: TrackOutput + + a_BlockEntities.push_back(CmdBlock.release()); +} + + + + + void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, const char * a_IDTag, int a_IDTagLength) { if (strncmp(a_IDTag, "Boat", a_IDTagLength) == 0) diff --git a/src/WorldStorage/WSSAnvil.h b/src/WorldStorage/WSSAnvil.h index e66e63b08..5093ad083 100644 --- a/src/WorldStorage/WSSAnvil.h +++ b/src/WorldStorage/WSSAnvil.h @@ -131,14 +131,15 @@ protected: */ void LoadItemGridFromNBT(cItemGrid & a_ItemGrid, const cParsedNBT & a_NBT, int a_ItemsTagIdx, int s_SlotOffset = 0); - 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 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); - void LoadNoteFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); - void LoadSignFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); + 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 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); + void LoadNoteFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); + void LoadSignFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); + void LoadCommandBlockFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, const char * a_IDTag, int a_IDTagLength); -- cgit v1.2.3 From 1ad6469a180dfe6932c756fe3c99bcada3ee0b7e Mon Sep 17 00:00:00 2001 From: andrew Date: Sat, 18 Jan 2014 16:59:33 +0200 Subject: Command blocks: Execute() --- src/Bindings/ManualBindings.cpp | 22 ++++++++++++---------- src/BlockEntities/CommandBlockEntity.cpp | 32 +++++++++++++++++++++++++++----- src/Server.cpp | 2 +- src/World.h | 2 +- src/WorldStorage/WSSAnvil.cpp | 2 +- 5 files changed, 42 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index ebee2d697..3ebe7b294 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -14,6 +14,7 @@ #include "../WebAdmin.h" #include "../ClientHandle.h" #include "../BlockEntities/ChestEntity.h" +#include "../BlockEntities/CommandBlockEntity.h" #include "../BlockEntities/DispenserEntity.h" #include "../BlockEntities/DropperEntity.h" #include "../BlockEntities/FurnaceEntity.h" @@ -2265,16 +2266,17 @@ void ManualBindings::Bind(lua_State * tolua_S) tolua_endmodule(tolua_S); tolua_beginmodule(tolua_S, "cWorld"); - tolua_function(tolua_S, "DoWithBlockEntityAt", tolua_DoWithXYZ); - tolua_function(tolua_S, "DoWithChestAt", tolua_DoWithXYZ); - tolua_function(tolua_S, "DoWithDispenserAt", tolua_DoWithXYZ); - tolua_function(tolua_S, "DoWithDropSpenserAt", tolua_DoWithXYZ); - tolua_function(tolua_S, "DoWithDropperAt", tolua_DoWithXYZ); - tolua_function(tolua_S, "DoWithEntityByID", tolua_DoWithID< cWorld, cEntity, &cWorld::DoWithEntityByID>); - tolua_function(tolua_S, "DoWithFurnaceAt", tolua_DoWithXYZ); - tolua_function(tolua_S, "DoWithNoteBlockAt", tolua_DoWithXYZ); - 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, "DoWithBlockEntityAt", tolua_DoWithXYZ); + tolua_function(tolua_S, "DoWithChestAt", tolua_DoWithXYZ); + tolua_function(tolua_S, "DoWithDispenserAt", tolua_DoWithXYZ); + tolua_function(tolua_S, "DoWithDropSpenserAt", tolua_DoWithXYZ); + tolua_function(tolua_S, "DoWithDropperAt", tolua_DoWithXYZ); + tolua_function(tolua_S, "DoWithEntityByID", tolua_DoWithID< cWorld, cEntity, &cWorld::DoWithEntityByID>); + tolua_function(tolua_S, "DoWithFurnaceAt", tolua_DoWithXYZ); + tolua_function(tolua_S, "DoWithNoteBlockAt", tolua_DoWithXYZ); + tolua_function(tolua_S, "DoWithCommandBlockAt", tolua_DoWithXYZ); + 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); tolua_function(tolua_S, "ForEachChestInChunk", tolua_ForEachInChunk); tolua_function(tolua_S, "ForEachEntity", tolua_ForEach< cWorld, cEntity, &cWorld::ForEachEntity>); diff --git a/src/BlockEntities/CommandBlockEntity.cpp b/src/BlockEntities/CommandBlockEntity.cpp index 88e55dece..e70e259aa 100644 --- a/src/BlockEntities/CommandBlockEntity.cpp +++ b/src/BlockEntities/CommandBlockEntity.cpp @@ -8,6 +8,10 @@ #include "CommandBlockEntity.h" #include "../Entities/Player.h" +#include "CommandOutput.h" +#include "Root.h" +#include "Server.h" // ExecuteConsoleCommand() + @@ -45,7 +49,8 @@ void cCommandBlockEntity::UsedBy(cPlayer * a_Player) cWindow * Window = GetWindow(); if (Window == NULL) { - //OpenWindow(new cDropSpenserWindow(m_PosX, m_PosY, m_PosZ, this)); FIXME + // TODO 2014-01-18 xdot: Open the appropriate window. + // OpenWindow(new cCommandBlockWindow(m_PosX, m_PosY, m_PosZ, this)); Window = GetWindow(); } @@ -64,7 +69,7 @@ void cCommandBlockEntity::UsedBy(cPlayer * a_Player) void cCommandBlockEntity::SetCommand(const AString & a_Cmd) { - m_Command = a_Cmd;LOGD("Hrey %s", a_Cmd.c_str()); + m_Command = a_Cmd; } @@ -190,11 +195,28 @@ void cCommandBlockEntity::SaveToJson(Json::Value & a_Value) void cCommandBlockEntity::Execute() { - // TODO: Parse arguments and dispatch command + class CommandBlockOutCb : + public cCommandOutputCallback + { + cCommandBlockEntity* m_CmdBlock; + + public: + CommandBlockOutCb(cCommandBlockEntity* a_CmdBlock) : m_CmdBlock(a_CmdBlock) {} + + virtual void Out(const AString & a_Text) + { + ASSERT(m_CmdBlock != NULL); + + // Overwrite field + m_CmdBlock->SetLastOutput(a_Text); + } + } CmdBlockOutCb(this); + + cServer* Server = cRoot::Get()->GetServer(); - LOGD("Command: %s", m_Command.c_str()); + Server->ExecuteConsoleCommand(m_Command, CmdBlockOutCb); - m_LastOutput = ""; + // TODO 2014-01-18 xdot: Update the signal strength. m_Result = 0; } diff --git a/src/Server.cpp b/src/Server.cpp index 49067c17f..5280270b9 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -459,7 +459,7 @@ void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallbac { return; } - + // Special handling: "stop" and "restart" are built in if ((split[0].compare("stop") == 0) || (split[0].compare("restart") == 0)) { diff --git a/src/World.h b/src/World.h index c410e658e..1a7ad0cb1 100644 --- a/src/World.h +++ b/src/World.h @@ -469,7 +469,7 @@ public: 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 + bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & 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/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 85821fa51..96a77152b 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -948,7 +948,7 @@ void cWSSAnvil::LoadCommandBlockFromNBT(cBlockEntityList & a_BlockEntities, cons CmdBlock->SetLastOutput(a_NBT.GetString(currentLine)); } - // FIXME: TrackOutput + // TODO 2014-01-18 xdot: Figure out what TrackOutput is and parse it. a_BlockEntities.push_back(CmdBlock.release()); } -- cgit v1.2.3 From 02c9aa2b1e86974df4ef8ea152465719169bdac5 Mon Sep 17 00:00:00 2001 From: andrew Date: Sat, 18 Jan 2014 19:58:46 +0200 Subject: Parse the MC|AdvCdm plugin message --- src/BlockEntities/CommandBlockEntity.cpp | 2 + src/ClientHandle.cpp | 64 ++++++++++++++++++++++++++++++++ src/ClientHandle.h | 3 ++ src/WorldStorage/NBTChunkSerializer.cpp | 2 +- 4 files changed, 70 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/BlockEntities/CommandBlockEntity.cpp b/src/BlockEntities/CommandBlockEntity.cpp index e70e259aa..c29e3dff8 100644 --- a/src/BlockEntities/CommandBlockEntity.cpp +++ b/src/BlockEntities/CommandBlockEntity.cpp @@ -212,6 +212,8 @@ void cCommandBlockEntity::Execute() } } CmdBlockOutCb(this); + LOGD("cCommandBlockEntity: Executing command %s", m_Command.c_str()); + cServer* Server = cRoot::Get()->GetServer(); Server->ExecuteConsoleCommand(m_Command, CmdBlockOutCb); diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index c8513d516..0a97ba6c8 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -8,6 +8,7 @@ #include "Entities/Player.h" #include "Inventory.h" #include "BlockEntities/ChestEntity.h" +#include "BlockEntities/CommandBlockEntity.h" #include "BlockEntities/SignEntity.h" #include "UI/Window.h" #include "Item.h" @@ -545,6 +546,15 @@ 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 + { + const char* Data = a_Message.c_str(); + + HandleCommandBlockMessage(Data, a_Message.size()); + + return; + } + cPluginManager::Get()->CallHookPluginMessage(*this, a_Channel, a_Message); } @@ -552,6 +562,60 @@ void cClientHandle::HandlePluginMessage(const AString & a_Channel, const AString +void cClientHandle::HandleCommandBlockMessage(const char* a_Data, unsigned int a_Length) +{ + if (a_Length < 14) + { + LOGD("Malformed MC|AdvCdm packet."); + return; + } + + int BlockX, BlockY, BlockZ; + + AString Command; + + switch (a_Data[0]) + { + case 0x00: + { + BlockX = GetBEInt(a_Data + 1); + BlockY = GetBEInt(a_Data + 5); + BlockZ = GetBEInt(a_Data + 9); + + Command = AString(a_Data + 14, (int)a_Data[13]); + break; + } + + default: + { + LOGD("Unhandled MC|AdvCdm packet mode."); + return; + } + } + + class cUpdateCommandBlock : + public cCommandBlockCallback + { + AString m_Command; + public: + cUpdateCommandBlock(const AString & a_Command) : m_Command(a_Command) {} + + virtual bool Item(cCommandBlockEntity * a_CommandBlock) override + { + a_CommandBlock->SetCommand(m_Command); + return false; + } + } CmdBlockCB (Command); + + cWorld * World = m_Player->GetWorld(); + + World->DoWithCommandBlockAt(BlockX, BlockY, BlockZ, CmdBlockCB); +} + + + + + void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status) { LOGD("HandleLeftClick: {%i, %i, %i}; Face: %i; Stat: %i", diff --git a/src/ClientHandle.h b/src/ClientHandle.h index da2704b72..373ca9e2e 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -324,6 +324,9 @@ private: /// Handles the DIG_FINISHED dig packet: void HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_OldBlock, NIBBLETYPE a_OldMeta); + + /// Handles the "MC|AdvCdm" plugin message + void HandleCommandBlockMessage(const char* a_Data, unsigned int a_Length); // cSocketThreads::cCallback overrides: virtual void DataReceived (const char * a_Data, int a_Size) override; // Data is received from the client diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index b5b5e555b..447296c7f 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -236,7 +236,7 @@ void cNBTChunkSerializer::AddCommandBlockEntity(cCommandBlockEntity * a_CmdBlock m_Writer.AddString("Command", a_CmdBlock->GetCommand()); m_Writer.AddInt ("SuccessCount", a_CmdBlock->GetResult()); m_Writer.AddString("LastOutput", a_CmdBlock->GetLastOutput()); - m_Writer.AddByte ("TrackOutput", 1); // Unknown (?) + m_Writer.AddByte ("TrackOutput", 1); // TODO 2014-01-18 xdot: Figure out what TrackOutput is and save it. m_Writer.EndCompound(); } -- cgit v1.2.3 From a037172465932de7d0d7d725c3c8ec5b2fa44029 Mon Sep 17 00:00:00 2001 From: andrew Date: Sat, 18 Jan 2014 21:27:54 +0200 Subject: Command block fixes --- src/BlockEntities/CommandBlockEntity.cpp | 36 +++----------------------------- src/BlockEntities/CommandBlockEntity.h | 7 ++----- src/ClientHandle.cpp | 17 ++++++++++----- 3 files changed, 17 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/BlockEntities/CommandBlockEntity.cpp b/src/BlockEntities/CommandBlockEntity.cpp index c29e3dff8..543d47b7a 100644 --- a/src/BlockEntities/CommandBlockEntity.cpp +++ b/src/BlockEntities/CommandBlockEntity.cpp @@ -20,24 +20,7 @@ cCommandBlockEntity::cCommandBlockEntity(int a_X, int a_Y, int a_Z, cWorld * a_W 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(); - } -} +{} @@ -46,21 +29,8 @@ cCommandBlockEntity::~cCommandBlockEntity() void cCommandBlockEntity::UsedBy(cPlayer * a_Player) { - cWindow * Window = GetWindow(); - if (Window == NULL) - { - // TODO 2014-01-18 xdot: Open the appropriate window. - // OpenWindow(new cCommandBlockWindow(m_PosX, m_PosY, m_PosZ, this)); - Window = GetWindow(); - } - - if (Window != NULL) - { - if (a_Player->GetWindow() != Window) - { - a_Player->OpenWindow(Window); - } - } + // Nothing to do + UNUSED(a_Player); } diff --git a/src/BlockEntities/CommandBlockEntity.h b/src/BlockEntities/CommandBlockEntity.h index c4529a1e6..12157670f 100644 --- a/src/BlockEntities/CommandBlockEntity.h +++ b/src/BlockEntities/CommandBlockEntity.h @@ -9,8 +9,7 @@ #pragma once -#include "BlockEntityWithItems.h" -#include "../UI/WindowOwner.h" +#include "BlockEntity.h" @@ -28,8 +27,7 @@ namespace Json // tolua_begin class cCommandBlockEntity : - public cBlockEntity, - public cBlockEntityWindowOwner + public cBlockEntity { typedef cBlockEntity super; @@ -39,7 +37,6 @@ public: /// 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; diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 0a97ba6c8..faf583fbb 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -570,19 +570,26 @@ void cClientHandle::HandleCommandBlockMessage(const char* a_Data, unsigned int a return; } + cByteBuffer Buffer(a_Length); + Buffer.Write(a_Data, a_Length); + int BlockX, BlockY, BlockZ; AString Command; - switch (a_Data[0]) + char Mode; + + Buffer.ReadChar(Mode); + + switch (Mode) { case 0x00: { - BlockX = GetBEInt(a_Data + 1); - BlockY = GetBEInt(a_Data + 5); - BlockZ = GetBEInt(a_Data + 9); + Buffer.ReadBEInt(BlockX); + Buffer.ReadBEInt(BlockY); + Buffer.ReadBEInt(BlockZ); - Command = AString(a_Data + 14, (int)a_Data[13]); + Buffer.ReadVarUTF8String(Command); break; } -- cgit v1.2.3