1
0
Fork 0

Added bed entity (#3823)

* Added bed entity

* Export cBedEntity to lua
* Set color of bed through item damage value
* Added bed entity to APIDoc
* NBT: Added loading and saving
* Crafting recipes for the colored beds
This commit is contained in:
Lukas Pioch 2017-07-07 09:31:45 +02:00 committed by GitHub
parent 10a3bd9d12
commit 885d828712
28 changed files with 425 additions and 13 deletions

View File

@ -155,6 +155,46 @@ return
},
Inherits = "cBlockEntityWithItems",
},
cBedEntity =
{
Desc = [[
A bed entity is a {{cBlockEntity}} descendant that represents a bed in the world.
]],
Functions =
{
GetColor =
{
Returns =
{
{
Type = "number",
},
},
Notes = "Returns the color of the bed.",
},
SetColor =
{
Params =
{
{
Type = "number",
},
},
Notes = "Set the color of the bed. A value between 0 - 15. The wool meta color values can be used.",
},
IsPillowBlock =
{
Returns =
{
{
Type = "boolean",
},
},
Notes = "Returns true if this is the pillow block, it has then the meta 8.",
},
},
Inherits = "cBlockEntity",
},
cBlockEntity =
{
Desc = [[

View File

@ -505,6 +505,35 @@ function OnAllChunksAvailable()</pre> All return values from the callbacks are i
},
Notes = "If there is a beacon at the specified coords, calls the CallbackFunction with the {{cBeaconEntity}} parameter representing the beacon. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cBeaconEntity|BeaconEntity}})</pre> The function returns false if there is no beacon, or if there is, it returns the bool value that the callback has returned.",
},
DoWithBedAt =
{
Params =
{
{
Name = "BlockX",
Type = "number",
},
{
Name = "BlockY",
Type = "number",
},
{
Name = "BlockZ",
Type = "number",
},
{
Name = "CallbackFunction",
Type = "function",
},
},
Returns =
{
{
Type = "boolean",
},
},
Notes = "If there is a bed at the specified coords, calls the CallbackFunction with the {{cBedEntity}} parameter representing the bed. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cBedEntity|cBedEntity}})</pre> The function returns false if there is no bed, or if there is, it returns the bool value that the callback has returned.",
},
DoWithBlockEntityAt =
{
Params =

View File

@ -383,7 +383,6 @@ AcaciaFenceGate = Stick, 1:1, 1:2, 3:1, 3:2 | AcaciaPlanks, 2:1, 2:2
Anvil = IronBlock, 1:1, 2:1, 3:1 | IronIngot, 2:2, 1:3, 2:3, 3:3
ArmorStand = Stick, 1:1, 1:3, 2:1, 2:2, 3:1, 3:3 | StoneSlab, 2:3
Beacon = Glass, 1:1, 1:2, 2:1, 3:1, 3:2 | Obsidian, 1:3, 2:3, 3:3 | NetherStar, 2:2
Bed = Planks^-1, 1:2, 2:2, 3:2 | Wool^-1, 1:1, 2:1, 3:1
BirchFence, 3 = BirchPlanks, 1:1, 1:2, 3:1, 3:2 | Stick, 2:1, 2:2
BirchFenceGate = Stick, 1:1, 1:2, 3:1, 3:2 | BirchPlanks, 2:1, 2:2
Bookandquill = Book, * | feather, * | inksac, *
@ -949,3 +948,24 @@ FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye
FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, *
FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, *
FireworkStar = FireworkStar, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, * | Dye ^-1, *
#******************************************************#
# Bed different colors
Bed^0 = Planks^-1, 1:2, 2:2, 3:2 | Wool^0, 1:1, 2:1, 3:1
Bed^1 = Planks^-1, 1:2, 2:2, 3:2 | Wool^1, 1:1, 2:1, 3:1
Bed^2 = Planks^-1, 1:2, 2:2, 3:2 | Wool^2, 1:1, 2:1, 3:1
Bed^3 = Planks^-1, 1:2, 2:2, 3:2 | Wool^3, 1:1, 2:1, 3:1
Bed^4 = Planks^-1, 1:2, 2:2, 3:2 | Wool^4, 1:1, 2:1, 3:1
Bed^5 = Planks^-1, 1:2, 2:2, 3:2 | Wool^5, 1:1, 2:1, 3:1
Bed^6 = Planks^-1, 1:2, 2:2, 3:2 | Wool^6, 1:1, 2:1, 3:1
Bed^7 = Planks^-1, 1:2, 2:2, 3:2 | Wool^7, 1:1, 2:1, 3:1
Bed^8 = Planks^-1, 1:2, 2:2, 3:2 | Wool^8, 1:1, 2:1, 3:1
Bed^9 = Planks^-1, 1:2, 2:2, 3:2 | Wool^9, 1:1, 2:1, 3:1
Bed^10 = Planks^-1, 1:2, 2:2, 3:2 | Wool^10, 1:1, 2:1, 3:1
Bed^11 = Planks^-1, 1:2, 2:2, 3:2 | Wool^11, 1:1, 2:1, 3:1
Bed^12 = Planks^-1, 1:2, 2:2, 3:2 | Wool^12, 1:1, 2:1, 3:1
Bed^13 = Planks^-1, 1:2, 2:2, 3:2 | Wool^13, 1:1, 2:1, 3:1
Bed^14 = Planks^-1, 1:2, 2:2, 3:2 | Wool^14, 1:1, 2:1, 3:1
Bed^15 = Planks^-1, 1:2, 2:2, 3:2 | Wool^15, 1:1, 2:1, 3:1

View File

@ -100,6 +100,7 @@ $cfile "../Mobs/Monster.h"
// Block entities:
$cfile "../BlockEntities/BlockEntity.h"
$cfile "../BlockEntities/BeaconEntity.h"
$cfile "../BlockEntities/BedEntity.h"
$cfile "../BlockEntities/BlockEntityWithItems.h"
$cfile "../BlockEntities/BrewingstandEntity.h"
$cfile "../BlockEntities/ChestEntity.h"

View File

@ -66,6 +66,7 @@ set(BINDING_DEPENDENCIES
../BiomeDef.h
../BlockArea.h
../BlockEntities/BeaconEntity.h
../BlockEntities/BedEntity.h
../BlockEntities/BlockEntity.h
../BlockEntities/BlockEntityWithItems.h
../BlockEntities/BrewingstandEntity.h

View File

@ -639,6 +639,7 @@ void cManualBindings::BindWorld(lua_State * tolua_S)
tolua_function(tolua_S, "ChunkStay", tolua_cWorld_ChunkStay);
tolua_function(tolua_S, "DoExplosionAt", tolua_cWorld_DoExplosionAt);
tolua_function(tolua_S, "DoWithBeaconAt", DoWithXYZ<cWorld, cBeaconEntity, &cWorld::DoWithBeaconAt>);
tolua_function(tolua_S, "DoWithBedAt", DoWithXYZ<cWorld, cBedEntity, &cWorld::DoWithBedAt>);
tolua_function(tolua_S, "DoWithBlockEntityAt", DoWithXYZ<cWorld, cBlockEntity, &cWorld::DoWithBlockEntityAt>);
tolua_function(tolua_S, "DoWithBrewingstandAt", DoWithXYZ<cWorld, cBrewingstandEntity, &cWorld::DoWithBrewingstandAt>);
tolua_function(tolua_S, "DoWithChestAt", DoWithXYZ<cWorld, cChestEntity, &cWorld::DoWithChestAt>);

View File

@ -0,0 +1,56 @@
// BedEntity.cpp
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "BedEntity.h"
#include "../World.h"
#include "../Entities/Player.h"
#include "../ClientHandle.h"
#include "../Blocks/BlockBed.h"
cBedEntity::cBedEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World, short a_Color):
Super(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World),
m_Color(a_Color)
{
ASSERT(a_BlockType == E_BLOCK_BED);
}
void cBedEntity::CopyFrom(const cBlockEntity & a_Src)
{
Super::CopyFrom(a_Src);
auto & src = reinterpret_cast<const cBedEntity &>(a_Src);
m_Color = src.m_Color;
}
void cBedEntity::SendTo(cClientHandle & a_Client)
{
a_Client.SendUpdateBlockEntity(*this);
}
void cBedEntity::SetColor(short a_Color)
{
m_Color = a_Color;
int posX = m_PosX;
int posY = m_PosY;
int posZ = m_PosZ;
// If the bed entity is send immediately, the client (maybe) still has not the bed.
// Fix that by delaying the broadcast of the bed entity by a tick:
m_World->ScheduleTask(1, [posX, posY, posZ](cWorld & a_World)
{
a_World.BroadcastBlockEntity(posX, posY, posZ);
});
}

View File

@ -0,0 +1,45 @@
// BedEntity.h
#pragma once
#include "BlockEntity.h"
// tolua_begin
class cBedEntity :
public cBlockEntity
{
typedef cBlockEntity Super;
public:
// tolua_end
BLOCKENTITY_PROTODEF(cBedEntity)
cBedEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World, short a_Color = E_META_WOOL_RED);
// tolua_begin
/** Returns the color of the bed */
short GetColor(void) const { return m_Color; }
/** Set the color of the bed. */
void SetColor(short a_Color);
/** Returns true if this is the pillow block, it has then the meta 8. */
bool IsPillowBlock(void) { return ((m_BlockMeta & 0x08) == 0x08); }
// tolua_end
// cBlockEntity overrides:
virtual void CopyFrom(const cBlockEntity & a_Src) override;
virtual bool UsedBy(cPlayer * a_Player) override { return false; }
virtual void SendTo(cClientHandle & a_Client) override;
private:
short m_Color;
}; // tolua_export

View File

@ -5,6 +5,7 @@
#include "Globals.h"
#include "BeaconEntity.h"
#include "BedEntity.h"
#include "BlockEntity.h"
#include "BrewingstandEntity.h"
#include "ChestEntity.h"
@ -42,6 +43,7 @@ bool cBlockEntity::IsBlockEntityBlockType(BLOCKTYPE a_BlockType)
switch (a_BlockType)
{
case E_BLOCK_BEACON:
case E_BLOCK_BED:
case E_BLOCK_BREWING_STAND:
case E_BLOCK_CHEST:
case E_BLOCK_COMMAND_BLOCK:
@ -75,6 +77,7 @@ cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE
switch (a_BlockType)
{
case E_BLOCK_BEACON: return new cBeaconEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_BED: return new cBedEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_BREWING_STAND: return new cBrewingstandEntity(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_CHEST: return new cChestEntity (a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_COMMAND_BLOCK: return new cCommandBlockEntity(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, a_World);

View File

@ -4,6 +4,7 @@ include_directories ("${PROJECT_SOURCE_DIR}/../")
SET (SRCS
BeaconEntity.cpp
BedEntity.cpp
BlockEntity.cpp
BlockEntityWithItems.cpp
BrewingstandEntity.cpp
@ -25,6 +26,7 @@ SET (SRCS
SET (HDRS
BeaconEntity.h
BedEntity.h
BlockEntity.h
BlockEntityWithItems.h
BrewingstandEntity.h

View File

@ -1,3 +1,6 @@
// BlockBed.cpp
#include "Globals.h"
#include "BlockBed.h"
@ -7,6 +10,7 @@
#include "../BoundingBox.h"
#include "../Mobs/Monster.h"
#include "../Entities/Entity.h"
#include "../BlockEntities/BedEntity.h"
@ -16,14 +20,19 @@ void cBlockBedHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInt
{
NIBBLETYPE OldMeta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
Vector3i ThisPos( a_BlockX, a_BlockY, a_BlockZ);
Vector3i Direction = MetaDataToDirection( OldMeta & 0x3);
Vector3i ThisPos(a_BlockX, a_BlockY, a_BlockZ);
Vector3i Direction = MetaDataToDirection(OldMeta & 0x3);
if (OldMeta & 0x8)
{
// Was pillow
if (a_ChunkInterface.GetBlock(ThisPos - Direction) == E_BLOCK_BED)
{
// First replace the bed with air
a_ChunkInterface.FastSetBlock(ThisPos - Direction, E_BLOCK_AIR, 0);
// Then destroy the bed entity
Vector3i PillowPos(ThisPos - Direction);
a_ChunkInterface.SetBlock(PillowPos.x, PillowPos.y, PillowPos.z, E_BLOCK_AIR, 0);
}
}
else
@ -31,7 +40,12 @@ void cBlockBedHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInt
// Was foot end
if (a_ChunkInterface.GetBlock(ThisPos + Direction) == E_BLOCK_BED)
{
// First replace the bed with air
a_ChunkInterface.FastSetBlock(ThisPos + Direction, E_BLOCK_AIR, 0);
// Then destroy the bed entity
Vector3i FootPos(ThisPos + Direction);
a_ChunkInterface.SetBlock(FootPos.x, FootPos.y, FootPos.z, E_BLOCK_AIR, 0);
}
}
}
@ -169,4 +183,48 @@ bool cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface
void cBlockBedHandler::OnPlacedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, const sSetBlock & a_BlockChange)
{
class cBedColor :
public cBedCallback
{
public:
short m_Color;
cBedColor(short a_Color) :
m_Color(a_Color)
{
}
virtual bool Item(cBedEntity * a_Bed) override
{
a_Bed->SetColor(m_Color);
return true;
}
};
cBedColor BedCallback(a_Player->GetEquippedItem().m_ItemDamage);
a_Player->GetWorld()->DoWithBedAt(a_BlockChange.GetX(), a_BlockChange.GetY(), a_BlockChange.GetZ(), BedCallback);
}
void cBlockBedHandler::ConvertToPickups(cEntity * a_Digger, cItems & a_Pickups, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
{
class cBedColor :
public cBedCallback
{
public:
short m_Color = E_META_WOOL_RED;
virtual bool Item(cBedEntity * a_Bed) override
{
m_Color = a_Bed->GetColor();
return true;
}
};
cBedColor BedCallback;
a_Digger->GetWorld()->DoWithBedAt(a_BlockX, a_BlockY, a_BlockZ, BedCallback);
a_Pickups.Add(cItem(E_ITEM_BED, 1, BedCallback.m_Color));
}

View File

@ -1,10 +1,14 @@
// BlockBed.h
#pragma once
#include "BlockEntity.h"
#include "BlockHandler.h"
#include "MetaRotator.h"
#include "Item.h"
#include "ChunkInterface.h"
#include "../World.h"
#include "../Entities/Entity.h"
class cPlayer;
@ -14,15 +18,16 @@ class cWorldInterface;
class cBlockBedHandler :
public cMetaRotator<cBlockHandler, 0x3, 0x02, 0x03, 0x00, 0x01, true>
public cMetaRotator<cBlockEntityHandler, 0x3, 0x02, 0x03, 0x00, 0x01, true>
{
public:
cBlockBedHandler(BLOCKTYPE a_BlockType)
: cMetaRotator<cBlockHandler, 0x3, 0x02, 0x03, 0x00, 0x01, true>(a_BlockType)
: cMetaRotator<cBlockEntityHandler, 0x3, 0x02, 0x03, 0x00, 0x01, true>(a_BlockType)
{
}
virtual void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual bool OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
virtual bool IsUseable(void) override
@ -30,11 +35,9 @@ public:
return true;
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to zero
a_Pickups.push_back(cItem(E_ITEM_BED, 1, 0));
}
virtual void ConvertToPickups(cItems & Pickups, NIBBLETYPE Meta) override {}
virtual void ConvertToPickups(cEntity * a_Digger, cItems & a_Pickups, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ) override;
// Bed specific helper functions
static NIBBLETYPE RotationToMetaData(double a_Rotation)
@ -77,6 +80,8 @@ public:
a_ChunkInterface.SetBlockMeta(a_BedPosition.x, a_BedPosition.y, a_BedPosition.z, Meta);
}
virtual void OnPlacedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, const sSetBlock & a_BlockChange) override;
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
{
UNUSED(a_Meta);

View File

@ -2,7 +2,7 @@
#pragma once
#include "BlockHandler.h"
#include "ChunkInterface.h"

View File

@ -463,7 +463,6 @@ void cBlockHandler::DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterfac
{
case E_BLOCK_ACACIA_DOOR:
case E_BLOCK_ACTIVE_COMPARATOR:
case E_BLOCK_BED:
case E_BLOCK_BEETROOTS:
case E_BLOCK_BIRCH_DOOR:
case E_BLOCK_BREWING_STAND:
@ -512,9 +511,19 @@ void cBlockHandler::DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterfac
ConvertToPickups(Pickups, Meta);
break;
}
case E_BLOCK_BED:
{
// Need to access the bed entity to get the color for the item damage
ConvertToPickups(a_Digger, Pickups, Meta, a_BlockX, a_BlockY, a_BlockZ);
}
default: Pickups.Add(m_BlockType, 1, Meta); break;
}
}
else if (m_BlockType == E_BLOCK_BED)
{
// Need to access the bed entity to get the color for the item damage
ConvertToPickups(a_Digger, Pickups, Meta, a_BlockX, a_BlockY, a_BlockZ);
}
else
{
ConvertToPickups(Pickups, Meta);

View File

@ -80,6 +80,10 @@ public:
/** Called when the item is mined to convert it into pickups. Pickups may specify multiple items. Appends items to a_Pickups, preserves its original contents */
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta);
/** Called when the item is mined to convert it into pickups. Pickups may specify multiple items. Appends items to a_Pickups, preserves its original contents.
Overloaded method with coords and digger, for blocks that needs to access the block entity, e.g. a bed */
virtual void ConvertToPickups(cEntity * a_Digger, cItems & a_Pickups, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ) {}
/** Handles the dropping, but not destruction, of a block based on what ConvertTo(Verbatim)Pickups() returns, including the spawning of pickups and alertion of plugins
@param a_Digger The entity causing the drop; it may be nullptr
@param a_CanDrop Informs the handler whether the block should be dropped at all. One example when this is false is when stone is destroyed by hand

View File

@ -13,6 +13,7 @@
#include "zlib/zlib.h"
#include "Defines.h"
#include "BlockEntities/BeaconEntity.h"
#include "BlockEntities/BedEntity.h"
#include "BlockEntities/BrewingstandEntity.h"
#include "BlockEntities/ChestEntity.h"
#include "BlockEntities/CommandBlockEntity.h"
@ -1404,6 +1405,7 @@ void cChunk::CreateBlockEntities(void)
switch (BlockType)
{
case E_BLOCK_BEACON:
case E_BLOCK_BED:
case E_BLOCK_TRAPPED_CHEST:
case E_BLOCK_CHEST:
case E_BLOCK_COMMAND_BLOCK:
@ -1537,6 +1539,7 @@ void cChunk::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType,
switch (a_BlockType)
{
case E_BLOCK_BEACON:
case E_BLOCK_BED:
case E_BLOCK_TRAPPED_CHEST:
case E_BLOCK_CHEST:
case E_BLOCK_COMMAND_BLOCK:
@ -2265,6 +2268,15 @@ bool cChunk::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCal
bool cChunk::DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback & a_Callback)
{
return GenericDoWithBlockEntityAt<cBedEntity,
E_BLOCK_BED
>(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
bool cChunk::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback & a_Callback)
{

View File

@ -30,6 +30,7 @@ class cServer;
class cPlayer;
class cChunkMap;
class cBeaconEntity;
class cBedEntity;
class cBrewingstandEntity;
class cBoundingBox;
class cChestEntity;
@ -53,6 +54,7 @@ class cSetChunkData;
typedef std::list<cClientHandle *> cClientHandleList;
typedef cItemCallback<cEntity> cEntityCallback;
typedef cItemCallback<cBeaconEntity> cBeaconCallback;
typedef cItemCallback<cBedEntity> cBedCallback;
typedef cItemCallback<cBrewingstandEntity> cBrewingstandCallback;
typedef cItemCallback<cChestEntity> cChestCallback;
typedef cItemCallback<cDispenserEntity> cDispenserCallback;
@ -317,6 +319,9 @@ public:
/** Calls the callback for the brewingstand at the specified coords; returns false if there's no brewingstand at those coords, true if found */
bool DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback & a_Callback); // Lua-acessible
/** Calls the callback for the bed at the specified coords; returns false if there's no bed at those coords, true if found */
bool DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback & a_Callback); // Lua-acessible
/** Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found */
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Lua-acessible

View File

@ -2042,6 +2042,24 @@ bool cChunkMap::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeacon
bool cChunkMap::DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback & 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_CSChunks);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
if ((Chunk == nullptr) || !Chunk->IsValid())
{
return false;
}
return Chunk->DoWithBedAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
bool cChunkMap::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback & a_Callback)
{
int ChunkX, ChunkZ;

View File

@ -19,6 +19,7 @@ class cChunkStay;
class cChunk;
class cPlayer;
class cBeaconEntity;
class cBedEntity;
class cBrewingstandEntity;
class cChestEntity;
class cDispenserEntity;
@ -44,6 +45,7 @@ typedef cChunk * cChunkPtr;
typedef cItemCallback<cEntity> cEntityCallback;
typedef cItemCallback<cBlockEntity> cBlockEntityCallback;
typedef cItemCallback<cBeaconEntity> cBeaconCallback;
typedef cItemCallback<cBedEntity> cBedCallback;
typedef cItemCallback<cBrewingstandEntity> cBrewingstandCallback;
typedef cItemCallback<cChestEntity> cChestCallback;
typedef cItemCallback<cDispenserEntity> cDispenserCallback;
@ -277,6 +279,10 @@ public:
Returns false if there's no beacon at those coords, true if found. */
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback); // Lua-acessible
/** Calls the callback for the bed at the specified coords.
Returns false if there's no bed at those coords, true if found. */
bool DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback & a_Callback); // Lua-acessible
/** Calls the callback for the brewingstand at the specified coords; returns false if there's no brewingstand at those coords, true if found */
bool DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback & a_Callback); // Lua-acessible

View File

@ -30,6 +30,7 @@ Implements the 1.11 protocol classes:
#include "../Mobs/IncludeAllMonsters.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/BedEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
#include "../BlockEntities/MobHeadEntity.h"
#include "../BlockEntities/MobSpawnerEntity.h"
@ -421,6 +422,17 @@ void cProtocol_1_11_0::WriteBlockEntity(cPacketizer & a_Pkt, const cBlockEntity
break;
}
case E_BLOCK_BED:
{
auto & BedEntity = reinterpret_cast<const cBedEntity &>(a_BlockEntity);
Writer.AddInt("x", BedEntity.GetPosX());
Writer.AddInt("y", BedEntity.GetPosY());
Writer.AddInt("z", BedEntity.GetPosZ());
Writer.AddInt("color", BedEntity.GetColor());
Writer.AddString("id", "Bed"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
break;
}
case E_BLOCK_COMMAND_BLOCK:
{
auto & CommandBlockEntity = reinterpret_cast<const cCommandBlockEntity &>(a_BlockEntity);

View File

@ -1269,6 +1269,33 @@ void cProtocol_1_12::SendLogin(const cPlayer & a_Player, const cWorld & a_World)
void cProtocol_1_12::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
{
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x09); // Update tile entity packet
Pkt.WritePosition64(a_BlockEntity.GetPosX(), a_BlockEntity.GetPosY(), 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
case E_BLOCK_BEACON: Action = 3; break; // Update beacon entity
case E_BLOCK_HEAD: Action = 4; break; // Update Mobhead entity
case E_BLOCK_FLOWER_POT: Action = 5; break; // Update flower pot
case E_BLOCK_BED: Action = 11; break; // Update bed color
default: ASSERT(!"Unhandled or unimplemented BlockEntity update request!"); break;
}
Pkt.WriteBEUInt8(Action);
WriteBlockEntity(Pkt, a_BlockEntity);
}
void cProtocol_1_12::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle)
{
ASSERT(m_State == 3); // In game mode?

View File

@ -59,6 +59,7 @@ public:
virtual void SendTeleportEntity(const cEntity & a_Entity) override;
virtual void SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) override;
virtual void SendTitleTimes(int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) override;
virtual void SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) override;
protected:
virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override;
virtual void HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) override;

View File

@ -1439,6 +1439,15 @@ bool cWorld::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCal
bool cWorld::DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback & a_Callback)
{
return m_ChunkMap->DoWithBedAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
}
bool cWorld::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback & a_Callback)
{
return m_ChunkMap->DoWithBrewingstandAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);

View File

@ -536,6 +536,9 @@ public:
/** Calls the callback for the beacon at the specified coords; returns false if there's no beacon at those coords, true if found */
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback); // Exported in ManualBindings.cpp
/** Calls the callback for the bed at the specified coords; returns false if there's no bed at those coords, true if found */
bool DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback & a_Callback); // Exported in ManualBindings.cpp
/** Calls the callback for the brewingstand at the specified coords; returns false if there's no brewingstand at those coords, true if found */
bool DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback & a_Callback); // Lua-acessible

View File

@ -11,6 +11,7 @@
#include "FastNBT.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/BedEntity.h"
#include "../BlockEntities/BrewingstandEntity.h"
#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
@ -197,6 +198,18 @@ void cNBTChunkSerializer::AddBeaconEntity(cBeaconEntity * a_Entity)
void cNBTChunkSerializer::AddBedEntity(cBedEntity * a_Entity)
{
m_Writer.BeginCompound("");
AddBasicTileEntity(a_Entity, "Bed");
m_Writer.AddInt("color", a_Entity->GetColor());
m_Writer.EndCompound();
}
void cNBTChunkSerializer::AddBrewingstandEntity(cBrewingstandEntity * a_Brewingstand)
{
m_Writer.BeginCompound("");
@ -970,6 +983,7 @@ void cNBTChunkSerializer::BlockEntity(cBlockEntity * a_Entity)
switch (a_Entity->GetBlockType())
{
case E_BLOCK_BEACON: AddBeaconEntity (reinterpret_cast<cBeaconEntity *> (a_Entity)); break;
case E_BLOCK_BED: AddBedEntity (reinterpret_cast<cBedEntity *> (a_Entity)); break;
case E_BLOCK_BREWING_STAND: AddBrewingstandEntity(reinterpret_cast<cBrewingstandEntity *>(a_Entity)); break;
case E_BLOCK_CHEST: AddChestEntity (reinterpret_cast<cChestEntity *> (a_Entity), a_Entity->GetBlockType()); break;
case E_BLOCK_COMMAND_BLOCK: AddCommandBlockEntity(reinterpret_cast<cCommandBlockEntity *>(a_Entity)); break;

View File

@ -21,6 +21,7 @@ class cEntity;
class cBlockEntity;
class cBoat;
class cBeaconEntity;
class cBedEntity;
class cBrewingstandEntity;
class cChestEntity;
class cCommandBlockEntity;
@ -98,6 +99,7 @@ protected:
// Block entities:
void AddBasicTileEntity (cBlockEntity * a_Entity, const char * a_EntityTypeID);
void AddBeaconEntity (cBeaconEntity * a_Entity);
void AddBedEntity (cBedEntity * a_Entity);
void AddBrewingstandEntity(cBrewingstandEntity * a_Brewingstand);
void AddChestEntity (cChestEntity * a_Entity, BLOCKTYPE a_ChestType);
void AddDispenserEntity (cDispenserEntity * a_Entity);

View File

@ -19,6 +19,7 @@
#include "../Root.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/BedEntity.h"
#include "../BlockEntities/BrewingstandEntity.h"
#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
@ -694,6 +695,7 @@ cBlockEntity * cWSSAnvil::LoadBlockEntityFromNBT(const cParsedNBT & a_NBT, int a
{
// Specific entity loaders:
case E_BLOCK_BEACON: return LoadBeaconFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_BED: return LoadBedFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_BREWING_STAND: return LoadBrewingstandFromNBT(a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_CHEST: return LoadChestFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
case E_BLOCK_COMMAND_BLOCK: return LoadCommandBlockFromNBT(a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ);
@ -976,6 +978,32 @@ cBlockEntity * cWSSAnvil::LoadBeaconFromNBT(const cParsedNBT & a_NBT, int a_TagI
cBlockEntity * cWSSAnvil::LoadBedFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Check if the data has a proper type:
static const AStringVector expectedTypes({ "Bed", "minecraft:bed" });
if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_BlockX, a_BlockY, a_BlockZ))
{
return nullptr;
}
// Use color red as default
short Color = E_META_WOOL_RED;
int ColorIDx = a_NBT.FindChildByName(a_TagIdx, "color");
if (ColorIDx >= 0)
{
Color = static_cast<short>(a_NBT.GetInt(ColorIDx));
}
auto Bed = cpp14::make_unique<cBedEntity>(a_BlockType, a_BlockMeta, a_BlockX, a_BlockY, a_BlockZ, m_World, Color);
return Bed.release();
}
cBlockEntity * cWSSAnvil::LoadBrewingstandFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Check if the data has a proper type:

View File

@ -156,6 +156,7 @@ protected:
bool CheckBlockEntityType(const cParsedNBT & a_NBT, int a_TagIdx, const AStringVector & a_ExpectedTypes, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadBeaconFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadBedFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadBrewingstandFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadChestFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * LoadCommandBlockFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ);