Basic command block implementation
This commit is contained in:
parent
9aca5b4b99
commit
9a9b51a513
@ -20,5 +20,6 @@ worktycho
|
||||
Sxw1212
|
||||
tonibm19
|
||||
Diusrex
|
||||
structinf (xdot)
|
||||
|
||||
Please add yourself to this list if you contribute to MCServer.
|
||||
|
@ -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"
|
||||
@ -24,6 +25,7 @@ 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_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);
|
||||
|
173
src/BlockEntities/CommandBlockEntity.cpp
Normal file
173
src/BlockEntities/CommandBlockEntity.cpp
Normal file
@ -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 = "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
85
src/BlockEntities/CommandBlockEntity.h
Normal file
85
src/BlockEntities/CommandBlockEntity.h
Normal file
@ -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
|
||||
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -46,6 +46,7 @@ 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
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -23,6 +23,7 @@ class cDropperEntity;
|
||||
class cDropSpenserEntity;
|
||||
class cFurnaceEntity;
|
||||
class cNoteEntity;
|
||||
class cCommandBlockEntity;
|
||||
class cPawn;
|
||||
class cPickup;
|
||||
class cChunkDataSerializer;
|
||||
@ -40,6 +41,7 @@ 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
|
||||
|
||||
|
@ -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"
|
||||
@ -220,6 +221,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
|
||||
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)
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -52,6 +52,7 @@ typedef cItemCallback<cChestEntity> cChestCallback;
|
||||
typedef cItemCallback<cDispenserEntity> cDispenserCallback;
|
||||
typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
|
||||
typedef cItemCallback<cNoteEntity> cNoteBlockCallback;
|
||||
typedef cItemCallback<cCommandBlockEntity> cCommandBlockCallback;
|
||||
|
||||
|
||||
|
||||
@ -467,6 +468,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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user