2014-01-18 15:16:47 +02:00
// 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 "CommandBlockEntity.h"
2014-01-19 00:54:38 +00:00
#include "../CommandOutput.h"
#include "../Root.h"
2014-07-17 22:15:34 +02:00
#include "../Server.h" // ExecuteConsoleCommand()
2014-08-29 13:41:50 +01:00
#include "../ChatColor.h"
2014-09-26 18:13:19 +01:00
#include "../World.h"
#include "../ClientHandle.h"
2014-01-18 16:59:33 +02:00
2014-01-18 15:16:47 +02:00
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 ),
2014-04-26 15:32:14 -07:00
m_IsPowered ( false ),
m_Result ( 0 )
2014-01-18 21:27:54 +02:00
{}
2014-01-18 15:16:47 +02:00
void cCommandBlockEntity :: UsedBy ( cPlayer * a_Player )
{
2014-01-18 21:27:54 +02:00
// Nothing to do
UNUSED ( a_Player );
2014-01-18 15:16:47 +02:00
}
void cCommandBlockEntity :: SetCommand ( const AString & a_Cmd )
{
2014-01-18 16:59:33 +02:00
m_Command = a_Cmd ;
2014-01-19 00:54:38 +00:00
/*
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 ());
2014-01-18 15:16:47 +02:00
}
2014-01-18 15:40:47 +02:00
void cCommandBlockEntity :: SetLastOutput ( const AString & a_LastOut )
{
2014-01-19 13:25:35 +00:00
m_World -> BroadcastBlockEntity ( GetPosX (), GetPosY (), GetPosZ ());
2014-01-18 15:40:47 +02:00
m_LastOutput = a_LastOut ;
}
void cCommandBlockEntity :: SetResult ( const NIBBLETYPE a_Result )
{
m_Result = a_Result ;
}
2014-01-18 15:16:47 +02:00
const AString & cCommandBlockEntity :: GetCommand ( void ) const
{
return m_Command ;
}
const AString & cCommandBlockEntity :: GetLastOutput ( void ) const
{
return m_LastOutput ;
}
2014-01-18 15:40:47 +02:00
NIBBLETYPE cCommandBlockEntity :: GetResult ( void ) const
{
return m_Result ;
}
2014-01-18 15:16:47 +02:00
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 )
{
2014-02-24 11:29:59 -08:00
UNUSED ( a_Dt );
UNUSED ( a_Chunk );
2014-01-18 15:16:47 +02:00
if ( ! m_ShouldExecute )
{
return false ;
}
m_ShouldExecute = false ;
Execute ();
return true ;
}
void cCommandBlockEntity :: SendTo ( cClientHandle & a_Client )
{
2014-01-19 19:42:25 +00:00
a_Client . SendUpdateBlockEntity ( * this );
2014-01-18 15:16:47 +02:00
}
void cCommandBlockEntity :: Execute ()
{
2014-10-20 21:55:07 +01:00
ASSERT ( m_World != nullptr ); // Execute should not be called before the command block is attached to a world
2014-09-01 13:33:17 +02:00
2014-08-31 21:14:42 +01:00
if ( ! m_World -> AreCommandBlocksEnabled ())
2014-01-23 14:57:04 +02:00
{
2014-08-31 21:14:42 +01:00
return ;
2014-01-23 14:57:04 +02:00
}
2014-01-18 16:59:33 +02:00
class CommandBlockOutCb :
public cCommandOutputCallback
{
2014-01-23 14:14:33 +01:00
cCommandBlockEntity * m_CmdBlock ;
2014-01-18 16:59:33 +02:00
public :
2014-01-23 14:14:33 +01:00
CommandBlockOutCb ( cCommandBlockEntity * a_CmdBlock ) : m_CmdBlock ( a_CmdBlock ) {}
2014-01-18 16:59:33 +02:00
virtual void Out ( const AString & a_Text )
{
// Overwrite field
2014-08-29 13:41:50 +01:00
m_CmdBlock -> SetLastOutput ( cClientHandle :: FormatChatPrefix ( m_CmdBlock -> GetWorld () -> ShouldUseChatPrefixes (), "SUCCESS" , cChatColor :: Green , cChatColor :: White ) + a_Text );
2014-01-18 16:59:33 +02:00
}
} CmdBlockOutCb ( this );
2014-08-30 22:24:04 +02:00
// Administrator commands are not executable by command blocks:
if (
2014-08-29 13:41:50 +01:00
( m_Command != "stop" ) &&
( m_Command != "restart" ) &&
( m_Command != "kick" ) &&
( m_Command != "ban" ) &&
( m_Command != "ipban" )
2014-08-30 22:24:04 +02:00
)
2014-08-29 13:41:50 +01:00
{
cServer * Server = cRoot :: Get () -> GetServer ();
LOGD ( "cCommandBlockEntity: Executing command %s" , m_Command . c_str ());
Server -> ExecuteConsoleCommand ( m_Command , CmdBlockOutCb );
}
else
{
SetLastOutput ( cClientHandle :: FormatChatPrefix ( GetWorld () -> ShouldUseChatPrefixes (), "FAILURE" , cChatColor :: Rose , cChatColor :: White ) + "Adminstration commands can not be executed" );
LOGD ( "cCommandBlockEntity: Prevented execution of administration command %s" , m_Command . c_str ());
}
2014-01-18 15:40:47 +02:00
2014-01-18 16:59:33 +02:00
// TODO 2014-01-18 xdot: Update the signal strength.
2014-01-18 15:40:47 +02:00
m_Result = 0 ;
2014-01-18 15:16:47 +02:00
}