Merged viable code from #5120

This commit is contained in:
x12xx12x 2023-10-03 23:37:18 +02:00
parent ebeb164d2b
commit 973d30703b
No known key found for this signature in database
GPG Key ID: 14A5FAFF1E5BD166
23 changed files with 856 additions and 16 deletions

View File

@ -13415,6 +13415,10 @@ end
{
Notes = "A villager trade window",
},
wtShulkerBox =
{
Notes = "A shulker box window",
},
wtWorkbench =
{
Notes = "A workbench (crafting table) window",

View File

@ -1583,6 +1583,47 @@ World:ForEachChestInChunk(Player:GetChunkX(), Player:GetChunkZ(),
},
Inherits = "cBlockEntity",
},
cShulkerBoxEntity =
{
Desc = [[
A shulker box entity is a {{cBlockEntityWithItems|cBlockEntityWithItems}} descendant that represents a shulker box
in the world.</p>
<p>
To manipulate a shulker box already in the game, you need to use {{cWorld}}'s callback mechanism with
either DoWithShulkerBoxAt() or ForEachShulkerBoxInChunk() function. See the code example below
]],
Constants =
{
ContentsHeight =
{
Notes = "Height of the contents' {{cItemGrid|ItemGrid}}, as required by the parent class, {{cBlockEntityWithItems}}",
},
ContentsWidth =
{
Notes = "Width of the contents' {{cItemGrid|ItemGrid}}, as required by the parent class, {{cBlockEntityWithItems}}",
},
},
AdditionalInfo =
{
{
Header = "Code example",
Contents = [[
The following example code sets the top-left item of each shulker box in the same chunk as Player to
64 * diamond:
<pre class="prettyprint lang-lua">
-- Player is a {{cPlayer}} object instance
local World = Player:GetWorld();
World:ForEachShulkerBoxInChunk(Player:GetChunkX(), Player:GetChunkZ(),
function (ShulkerBoxEntity)
ShulkerBoxEntity:SetSlot(0, 0, cItem(E_ITEM_DIAMOND, 64));
end
);
</pre>
]],
},
},
Inherits = "cBlockEntityWithItems",
},
cSignEntity =
{
Desc = [[

View File

@ -1144,6 +1144,35 @@ function OnAllChunksAvailable()</pre> All return values from the callbacks are i
},
Notes = "If there is the player with the uuid, calls the CallbackFunction with the {{cPlayer}} parameter representing the player. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cPlayer|Player}})</pre> The function returns false if the player was not found, or whatever bool value the callback returned if the player was found.",
},
DoWithShulkerBoxAt =
{
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 shulker box at the specified coords, calls the CallbackFunction with the {{cShulkerBoxEntity}} parameter representing the shulker box. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cShulkerBoxEntity|ShulkerBoxEntity}})</pre> The function returns false if there is no shulker box, or if there is, it returns the bool value that the callback has returned.",
},
DropBlockAsPickups =
{
Params =
@ -1437,6 +1466,31 @@ function OnAllChunksAvailable()</pre> All return values from the callbacks are i
},
Notes = "Calls the specified callback for each player in the loaded world. Returns true if all the players have been processed (including when there are zero players), or false if the callback function has aborted the enumeration by returning true. The callback function has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cPlayer|Player}})</pre> The callback should return false or no value to continue with the next player, or true to abort the enumeration.",
},
ForEachShulkerBoxInChunk =
{
Params =
{
{
Name = "ChunkX",
Type = "number",
},
{
Name = "ChunkZ",
Type = "number",
},
{
Name = "CallbackFunction",
Type = "function",
},
},
Returns =
{
{
Type = "boolean",
},
},
Notes = "Calls the specified callback for each shulker box in the chunk. Returns true if all shulker boxes in the chunk have been processed (including when there are zero shulker boxes), or false if the callback has aborted the enumeration by returning true. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cShulkerBoxEntity|ShulkerBoxEntity}})</pre> The callback should return false or no value to continue with the next shulker box, or true to abort the enumeration.",
},
GenerateChunk =
{
Params =

View File

@ -23,6 +23,7 @@
#include "../BlockEntities/NoteEntity.h"
#include "../BlockEntities/MobHeadEntity.h"
#include "../BlockEntities/FlowerPotEntity.h"
#include "../BlockEntities/ShulkerBoxEntity.h"
#include "../BoundingBox.h"
#include "BuildInfo.h"
#include "../ClientHandle.h"

View File

@ -1759,6 +1759,7 @@ void cManualBindings::BindWorld(lua_State * tolua_S)
tolua_function(tolua_S, "DoWithNoteBlockAt", DoWithBlockEntityAt<cNoteEntity, E_BLOCK_NOTE_BLOCK>);
tolua_function(tolua_S, "DoWithPlayer", DoWith<cWorld, cPlayer, &cWorld::DoWithPlayer>);
tolua_function(tolua_S, "DoWithPlayerByUUID", tolua_cWorld_DoWithPlayerByUUID);
tolua_function(tolua_S, "DoWithShulkerBoxAt", DoWithXYZ<cWorld, cShulkerBoxEntity, &cWorld::DoWithShulkerBoxAt>);
tolua_function(tolua_S, "FastSetBlock", tolua_cWorld_FastSetBlock);
tolua_function(tolua_S, "FindAndDoWithPlayer", DoWith<cWorld, cPlayer, &cWorld::FindAndDoWithPlayer>);
tolua_function(tolua_S, "ForEachBlockEntityInChunk", ForEachBlockEntityInChunk<cBlockEntity>);
@ -1770,6 +1771,7 @@ void cManualBindings::BindWorld(lua_State * tolua_S)
tolua_function(tolua_S, "ForEachFurnaceInChunk", ForEachBlockEntityInChunk<cFurnaceEntity, E_BLOCK_FURNACE, E_BLOCK_LIT_FURNACE>);
tolua_function(tolua_S, "ForEachLoadedChunk", tolua_cWorld_ForEachLoadedChunk);
tolua_function(tolua_S, "ForEachPlayer", ForEach<cWorld, cPlayer, &cWorld::ForEachPlayer>);
tolua_function(tolua_S, "ForEachShulkerBoxInChunk", ForEachInChunk<cWorld, cShulkerBoxEntity, &cWorld::ForEachShulkerBoxInChunk>);
tolua_function(tolua_S, "GetBlock", tolua_cWorld_GetBlock);
tolua_function(tolua_S, "GetBlockBlockLight", tolua_cWorld_GetBlockBlockLight);
tolua_function(tolua_S, "GetBlockInfo", tolua_cWorld_GetBlockInfo);

View File

@ -23,6 +23,7 @@
#include "MobSpawnerEntity.h"
#include "JukeboxEntity.h"
#include "NoteEntity.h"
#include "ShulkerBoxEntity.h"
#include "SignEntity.h"
@ -101,6 +102,24 @@ OwnedBlockEntity cBlockEntity::CreateByBlockType(const BLOCKTYPE a_BlockType, co
case E_BLOCK_LIT_FURNACE: return std::make_unique<cFurnaceEntity >(a_BlockType, a_BlockMeta, a_Pos, a_World);
case E_BLOCK_MOB_SPAWNER: return std::make_unique<cMobSpawnerEntity >(a_BlockType, a_BlockMeta, a_Pos, a_World);
case E_BLOCK_NOTE_BLOCK: return std::make_unique<cNoteEntity >(a_BlockType, a_BlockMeta, a_Pos, a_World);
case E_BLOCK_WHITE_SHULKER_BOX:
case E_BLOCK_ORANGE_SHULKER_BOX:
case E_BLOCK_MAGENTA_SHULKER_BOX:
case E_BLOCK_LIGHT_BLUE_SHULKER_BOX:
case E_BLOCK_YELLOW_SHULKER_BOX:
case E_BLOCK_LIME_SHULKER_BOX:
case E_BLOCK_PINK_SHULKER_BOX:
case E_BLOCK_GRAY_SHULKER_BOX:
case E_BLOCK_LIGHT_GRAY_SHULKER_BOX:
case E_BLOCK_CYAN_SHULKER_BOX:
case E_BLOCK_PURPLE_SHULKER_BOX:
case E_BLOCK_BLUE_SHULKER_BOX:
case E_BLOCK_BROWN_SHULKER_BOX:
case E_BLOCK_GREEN_SHULKER_BOX:
case E_BLOCK_RED_SHULKER_BOX:
case E_BLOCK_BLACK_SHULKER_BOX: return std::make_unique<cShulkerBoxEntity >(a_BlockType, a_BlockMeta, a_Pos, a_World);
case E_BLOCK_SIGN_POST: return std::make_unique<cSignEntity >(a_BlockType, a_BlockMeta, a_Pos, a_World);
case E_BLOCK_TRAPPED_CHEST: return std::make_unique<cChestEntity >(a_BlockType, a_BlockMeta, a_Pos, a_World);
case E_BLOCK_WALLSIGN: return std::make_unique<cSignEntity >(a_BlockType, a_BlockMeta, a_Pos, a_World);
@ -149,6 +168,24 @@ bool cBlockEntity::IsBlockEntityBlockType(const BLOCKTYPE a_BlockType)
case E_BLOCK_LIT_FURNACE:
case E_BLOCK_MOB_SPAWNER:
case E_BLOCK_NOTE_BLOCK:
case E_BLOCK_WHITE_SHULKER_BOX:
case E_BLOCK_ORANGE_SHULKER_BOX:
case E_BLOCK_MAGENTA_SHULKER_BOX:
case E_BLOCK_LIGHT_BLUE_SHULKER_BOX:
case E_BLOCK_YELLOW_SHULKER_BOX:
case E_BLOCK_LIME_SHULKER_BOX:
case E_BLOCK_PINK_SHULKER_BOX:
case E_BLOCK_GRAY_SHULKER_BOX:
case E_BLOCK_LIGHT_GRAY_SHULKER_BOX:
case E_BLOCK_CYAN_SHULKER_BOX:
case E_BLOCK_PURPLE_SHULKER_BOX:
case E_BLOCK_BLUE_SHULKER_BOX:
case E_BLOCK_BROWN_SHULKER_BOX:
case E_BLOCK_GREEN_SHULKER_BOX:
case E_BLOCK_RED_SHULKER_BOX:
case E_BLOCK_BLACK_SHULKER_BOX:
case E_BLOCK_SIGN_POST:
case E_BLOCK_STANDING_BANNER:
case E_BLOCK_TRAPPED_CHEST:

View File

@ -22,6 +22,7 @@ target_sources(
MobHeadEntity.cpp
MobSpawnerEntity.cpp
NoteEntity.cpp
ShulkerBoxEntity.cpp
SignEntity.cpp
BannerEntity.h
@ -45,5 +46,6 @@ target_sources(
MobHeadEntity.h
MobSpawnerEntity.h
NoteEntity.h
ShulkerBoxEntity.h
SignEntity.h
)

View File

@ -0,0 +1,229 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "ShulkerBoxEntity.h"
#include "../BlockInfo.h"
#include "../Item.h"
#include "../Entities/Player.h"
#include "../UI/ShulkerBoxWindow.h"
#include "../ClientHandle.h"
#include "../Mobs/Ocelot.h"
class cItemGrid;
cShulkerBoxEntity::cShulkerBoxEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_Pos, ContentsWidth, ContentsHeight, a_World),
m_NumActivePlayers(0)
{
}
void cShulkerBoxEntity::CopyFrom(const cBlockEntity & a_Src)
{
Super::CopyFrom(a_Src);
auto & src = static_cast<const cShulkerBoxEntity &>(a_Src);
m_Contents.CopyFrom(src.m_Contents);
m_NumActivePlayers = 0;
}
void cShulkerBoxEntity::OnRemoveFromWorld()
{
const auto Window = GetWindow();
if (Window != nullptr)
{
Window->OwnerDestroyed();
}
}
void cShulkerBoxEntity::SendTo(cClientHandle & a_Client)
{
a_Client.SendBlockAction(m_Pos.x, m_Pos.y, m_Pos.z, 1, 0, m_BlockType);
}
bool cShulkerBoxEntity::UsedBy(cPlayer * a_Player)
{
if (IsBlocked())
{
// Obstruction, don't open
return false;
}
cShulkerBoxEntity * ShulkerBox = this;
a_Player->GetStatManager().AddValue(Statistic::OpenShulkerBox);
// If the window is not created, open it anew:
cWindow * Window = ShulkerBox->GetWindow();
if (Window == nullptr)
{
ShulkerBox->OpenNewWindow();
Window = ShulkerBox->GetWindow();
}
// Open the window for the player:
if (Window != nullptr)
{
if (a_Player->GetWindow() != Window)
{
a_Player->OpenWindow(*Window);
}
}
// This is rather a hack
// Instead of marking the chunk as dirty upon chest contents change, we mark it dirty now
// We cannot properly detect contents change, but such a change doesn't happen without a player opening the chest first.
// The few false positives aren't much to worry about
auto chunkCoords = cChunkDef::BlockToChunk(m_Pos);
m_World->MarkChunkDirty(chunkCoords.m_ChunkX, chunkCoords.m_ChunkZ);
return true;
}
void cShulkerBoxEntity::OpenNewWindow(void)
{
OpenWindow(new cShulkerBoxWindow(this, m_CustomName));
}
bool cShulkerBoxEntity::IsShulkerBox(short a_ItemType)
{
switch (a_ItemType)
{
case E_BLOCK_WHITE_SHULKER_BOX:
case E_BLOCK_ORANGE_SHULKER_BOX:
case E_BLOCK_MAGENTA_SHULKER_BOX:
case E_BLOCK_LIGHT_BLUE_SHULKER_BOX:
case E_BLOCK_YELLOW_SHULKER_BOX:
case E_BLOCK_LIME_SHULKER_BOX:
case E_BLOCK_PINK_SHULKER_BOX:
case E_BLOCK_GRAY_SHULKER_BOX:
case E_BLOCK_LIGHT_GRAY_SHULKER_BOX:
case E_BLOCK_CYAN_SHULKER_BOX:
case E_BLOCK_PURPLE_SHULKER_BOX:
case E_BLOCK_BLUE_SHULKER_BOX:
case E_BLOCK_BROWN_SHULKER_BOX:
case E_BLOCK_GREEN_SHULKER_BOX:
case E_BLOCK_RED_SHULKER_BOX:
case E_BLOCK_BLACK_SHULKER_BOX:
return true;
}
return false;
}
Vector3i cShulkerBoxEntity::BlockMetaToObstructionCheckDirection(NIBBLETYPE a_BlockMeta)
{
switch (a_BlockMeta)
{
case BLOCK_FACE_XP: return Vector3i(1, 0, 0);
case BLOCK_FACE_XM: return Vector3i(-1, 0, 0);
case BLOCK_FACE_YP: return Vector3i(0, 1, 0);
case BLOCK_FACE_YM: return Vector3i(0, -1, 0);
case BLOCK_FACE_ZP: return Vector3i(0, 0, 1);
case BLOCK_FACE_ZM: return Vector3i(0, 0, -1);
}
return Vector3i();
}
bool cShulkerBoxEntity::IsBlocked()
{
Vector3i CheckPos = GetPos() + cShulkerBoxEntity::BlockMetaToObstructionCheckDirection(m_BlockMeta);
return (
(GetPosY() < cChunkDef::Height - 1) &&
(
!cBlockInfo::IsTransparent(GetWorld()->GetBlock(CheckPos)) ||
!cOcelot::IsCatSittingOnBlock(GetWorld(), Vector3d(CheckPos))
)
);
}
void cShulkerBoxEntity::OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum)
{
ASSERT(a_Grid == &m_Contents);
if (m_World == nullptr)
{
return;
}
// Have cBlockEntityWithItems update redstone and try to broadcast our window:
Super::OnSlotChanged(a_Grid, a_SlotNum);
cWindow * Window = GetWindow();
if (Window != nullptr)
{
Window->BroadcastWholeWindow();
}
m_World->MarkChunkDirty(GetChunkX(), GetChunkZ());
}
cItems cShulkerBoxEntity::ConvertToPickups() const
{
cItem ShulkerBoxDrop = cItem(GetBlockType(), 1, 0, "", m_CustomName);
Json::Value a_TagJson(Json::objectValue);
BlockEntityTagSerializer::WriteToJson(a_TagJson, ShulkerBoxDrop, GetContents());
ShulkerBoxDrop.m_BlockEntityTag = a_TagJson;
return ShulkerBoxDrop;
}
void cShulkerBoxEntity::Load(const cItem & a_Item)
{
auto a_ItemGrid = cItemGrid(3, 9);
BlockEntityTagSerializer::ParseFromJson(a_Item.m_BlockEntityTag, a_ItemGrid);
if (!a_Item.IsCustomNameEmpty())
{
m_CustomName = a_Item.m_CustomName;
}
m_Contents.CopyFrom(a_ItemGrid);
}

View File

@ -0,0 +1,78 @@
#pragma once
#include "BlockEntityWithItems.h"
#include "../Simulator/RedstoneSimulator.h"
class cClientHandle;
// tolua_begin
class cShulkerBoxEntity :
public cBlockEntityWithItems
{
// tolua_end
using Super = cBlockEntityWithItems;
// tolua_begin
public:
enum
{
ContentsHeight = 3,
ContentsWidth = 9,
} ;
// tolua_end
/** Constructor used for normal operation */
cShulkerBoxEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World);
// cBlockEntity overrides:
virtual cItems ConvertToPickups() const override;
virtual void CopyFrom(const cBlockEntity & a_Src) override;
virtual void OnRemoveFromWorld() override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual bool UsedBy(cPlayer * a_Player) override;
/** Opens a new shulker box window */
void OpenNewWindow();
/** Returns true if the chest should not be accessible by players. */
bool IsBlocked();
/** Gets the number of players who currently have this shulker box open */
int GetNumberOfPlayers(void) const { return m_NumActivePlayers; }
/** Sets the number of players who currently have this shulker box open */
void SetNumberOfPlayers(int a_NumActivePlayers) { m_NumActivePlayers = a_NumActivePlayers; }
/** Loads shulker box from item */
void Load(const cItem & a_Item);
static bool IsShulkerBox(short m_ItemType);
/** Custom name of a shulker box */
AString m_CustomName;
private:
/** Number of players who currently have this shulker box open */
int m_NumActivePlayers;
/** cItemGrid::cListener overrides: */
virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum) override;
/** Returns direction for obstruction check */
static Vector3i BlockMetaToObstructionCheckDirection(NIBBLETYPE a_BlockMeta);
} ; // tolua_export

View File

@ -82,6 +82,7 @@
#include "BlockSand.h"
#include "BlockSapling.h"
#include "BlockSeaLantern.h"
#include "BlockShulkerBox.h"
#include "BlockSideways.h"
#include "BlockSignPost.h"
#include "BlockSlab.h"
@ -214,9 +215,9 @@ namespace
constexpr cBlockFenceHandler BlockBirchFenceHandler (E_BLOCK_BIRCH_FENCE);
constexpr cBlockStairsHandler BlockBirchWoodStairsHandler (E_BLOCK_BIRCH_WOOD_STAIRS);
constexpr cBlockGlazedTerracottaHandler BlockBlackGlazedTerracottaHandler (E_BLOCK_BLACK_GLAZED_TERRACOTTA);
constexpr cDefaultBlockHandler BlockBlackShulkerBoxHandler (E_BLOCK_BLACK_SHULKER_BOX);
constexpr cBlockShulkerBoxHandler BlockBlackShulkerBoxHandler (E_BLOCK_BLACK_SHULKER_BOX);
constexpr cBlockGlazedTerracottaHandler BlockBlueGlazedTerracottaHandler (E_BLOCK_BLUE_GLAZED_TERRACOTTA);
constexpr cDefaultBlockHandler BlockBlueShulkerBoxHandler (E_BLOCK_BLUE_SHULKER_BOX);
constexpr cBlockShulkerBoxHandler BlockBlueShulkerBoxHandler (E_BLOCK_BLUE_SHULKER_BOX);
constexpr cDefaultBlockHandler BlockBoneBlockHandler (E_BLOCK_BONE_BLOCK);
constexpr cBlockBookShelfHandler BlockBookcaseHandler (E_BLOCK_BOOKCASE);
constexpr cBlockBrewingStandHandler BlockBrewingStandHandler (E_BLOCK_BREWING_STAND);
@ -224,7 +225,7 @@ namespace
constexpr cBlockStairsHandler BlockBrickStairsHandler (E_BLOCK_BRICK_STAIRS);
constexpr cBlockGlazedTerracottaHandler BlockBrownGlazedTerracottaHandler (E_BLOCK_BROWN_GLAZED_TERRACOTTA);
constexpr cBlockMushroomHandler BlockBrownMushroomHandler (E_BLOCK_BROWN_MUSHROOM);
constexpr cDefaultBlockHandler BlockBrownShulkerBoxHandler (E_BLOCK_BROWN_SHULKER_BOX);
constexpr cBlockShulkerBoxHandler BlockBrownShulkerBoxHandler (E_BLOCK_BROWN_SHULKER_BOX);
constexpr cBlockCactusHandler BlockCactusHandler (E_BLOCK_CACTUS);
constexpr cBlockCakeHandler BlockCakeHandler (E_BLOCK_CAKE);
constexpr cBlockCarpetHandler BlockCarpetHandler (E_BLOCK_CARPET);
@ -247,7 +248,7 @@ namespace
constexpr cBlockConcretePowderHandler BlockConcretePowderHandler (E_BLOCK_CONCRETE_POWDER);
constexpr cBlockCropsHandler<7> BlockCropsHandler (E_BLOCK_CROPS); // 8 stages of growth
constexpr cBlockGlazedTerracottaHandler BlockCyanGlazedTerracottaHandler (E_BLOCK_CYAN_GLAZED_TERRACOTTA);
constexpr cDefaultBlockHandler BlockCyanShulkerBoxHandler (E_BLOCK_CYAN_SHULKER_BOX);
constexpr cBlockShulkerBoxHandler BlockCyanShulkerBoxHandler (E_BLOCK_CYAN_SHULKER_BOX);
constexpr cBlockDoorHandler BlockDarkOakDoorHandler (E_BLOCK_DARK_OAK_DOOR);
constexpr cBlockFenceGateHandler BlockDarkOakFenceGateHandler (E_BLOCK_DARK_OAK_FENCE_GATE);
constexpr cBlockFenceHandler BlockDarkOakFenceHandler (E_BLOCK_DARK_OAK_FENCE);
@ -289,9 +290,9 @@ namespace
constexpr cDefaultBlockHandler BlockGrassPathHandler (E_BLOCK_GRASS_PATH);
constexpr cBlockGravelHandler BlockGravelHandler (E_BLOCK_GRAVEL);
constexpr cBlockGlazedTerracottaHandler BlockGrayGlazedTerracottaHandler (E_BLOCK_GRAY_GLAZED_TERRACOTTA);
constexpr cDefaultBlockHandler BlockGrayShulkerBoxHandler (E_BLOCK_GRAY_SHULKER_BOX);
constexpr cBlockShulkerBoxHandler BlockGrayShulkerBoxHandler (E_BLOCK_GRAY_SHULKER_BOX);
constexpr cBlockGlazedTerracottaHandler BlockGreenGlazedTerracottaHandler (E_BLOCK_GREEN_GLAZED_TERRACOTTA);
constexpr cDefaultBlockHandler BlockGreenShulkerBoxHandler (E_BLOCK_GREEN_SHULKER_BOX);
constexpr cBlockShulkerBoxHandler BlockGreenShulkerBoxHandler (E_BLOCK_GREEN_SHULKER_BOX);
constexpr cDefaultBlockHandler BlockHardenedClayHandler (E_BLOCK_HARDENED_CLAY);
constexpr cBlockSidewaysHandler BlockHayBaleHandler (E_BLOCK_HAY_BALE);
constexpr cBlockMobHeadHandler BlockHeadHandler (E_BLOCK_HEAD);
@ -320,17 +321,17 @@ namespace
constexpr cBlockLeavesHandler BlockLeavesHandler (E_BLOCK_LEAVES);
constexpr cBlockLeverHandler BlockLeverHandler (E_BLOCK_LEVER);
constexpr cBlockGlazedTerracottaHandler BlockLightBlueGlazedTerracoHandler(E_BLOCK_LIGHT_BLUE_GLAZED_TERRACOTTA);
constexpr cDefaultBlockHandler BlockLightBlueShulkerBoxHandler (E_BLOCK_LIGHT_BLUE_SHULKER_BOX);
constexpr cBlockShulkerBoxHandler BlockLightBlueShulkerBoxHandler (E_BLOCK_LIGHT_BLUE_SHULKER_BOX);
constexpr cBlockGlazedTerracottaHandler BlockLightGrayGlazedTerracoHandler(E_BLOCK_LIGHT_GRAY_GLAZED_TERRACOTTA);
constexpr cDefaultBlockHandler BlockLightGrayShulkerBoxHandler (E_BLOCK_LIGHT_GRAY_SHULKER_BOX);
constexpr cBlockShulkerBoxHandler BlockLightGrayShulkerBoxHandler (E_BLOCK_LIGHT_GRAY_SHULKER_BOX);
constexpr cBlockPressurePlateHandler BlockLightWeightedPressurePHandler(E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE);
constexpr cBlockLilypadHandler BlockLilyPadHandler (E_BLOCK_LILY_PAD);
constexpr cBlockGlazedTerracottaHandler BlockLimeGlazedTerracottaHandler (E_BLOCK_LIME_GLAZED_TERRACOTTA);
constexpr cDefaultBlockHandler BlockLimeShulkerBoxHandler (E_BLOCK_LIME_SHULKER_BOX);
constexpr cBlockShulkerBoxHandler BlockLimeShulkerBoxHandler (E_BLOCK_LIME_SHULKER_BOX);
constexpr cBlockFurnaceHandler BlockLitFurnaceHandler (E_BLOCK_LIT_FURNACE);
constexpr cBlockSidewaysHandler BlockLogHandler (E_BLOCK_LOG);
constexpr cBlockGlazedTerracottaHandler BlockMagentaGlazedTerracottHandler(E_BLOCK_MAGENTA_GLAZED_TERRACOTTA);
constexpr cDefaultBlockHandler BlockMagentaShulkerBoxHandler (E_BLOCK_MAGENTA_SHULKER_BOX);
constexpr cBlockShulkerBoxHandler BlockMagentaShulkerBoxHandler (E_BLOCK_MAGENTA_SHULKER_BOX);
constexpr cDefaultBlockHandler BlockMagmaHandler (E_BLOCK_MAGMA);
constexpr cBlockMelonHandler BlockMelonHandler (E_BLOCK_MELON);
constexpr cBlockMelonStemHandler BlockMelonStemHandler (E_BLOCK_MELON_STEM);
@ -354,10 +355,10 @@ namespace
constexpr cBlockObserverHandler BlockObserverHandler (E_BLOCK_OBSERVER);
constexpr cDefaultBlockHandler BlockObsidianHandler (E_BLOCK_OBSIDIAN);
constexpr cBlockGlazedTerracottaHandler BlockOrangeGlazedTerracottaHandler(E_BLOCK_ORANGE_GLAZED_TERRACOTTA);
constexpr cDefaultBlockHandler BlockOrangeShulkerBoxHandler (E_BLOCK_ORANGE_SHULKER_BOX);
constexpr cBlockShulkerBoxHandler BlockOrangeShulkerBoxHandler (E_BLOCK_ORANGE_SHULKER_BOX);
constexpr cBlockPackedIceHandler BlockPackedIceHandler (E_BLOCK_PACKED_ICE);
constexpr cBlockGlazedTerracottaHandler BlockPinkGlazedTerracottaHandler (E_BLOCK_PINK_GLAZED_TERRACOTTA);
constexpr cDefaultBlockHandler BlockPinkShulkerBoxHandler (E_BLOCK_PINK_SHULKER_BOX);
constexpr cBlockShulkerBoxHandler BlockPinkShulkerBoxHandler (E_BLOCK_PINK_SHULKER_BOX);
constexpr cBlockPistonHandler BlockPistonHandler (E_BLOCK_PISTON);
constexpr cBlockPistonHeadHandler BlockPistonHeadHandler;
constexpr cDefaultBlockHandler BlockPistonMovedBlockHandler (E_BLOCK_PISTON_MOVED_BLOCK);
@ -368,7 +369,7 @@ namespace
constexpr cBlockPumpkinHandler BlockPumpkinHandler (E_BLOCK_PUMPKIN);
constexpr cBlockPumpkinStemHandler BlockPumpkinStemHandler (E_BLOCK_PUMPKIN_STEM);
constexpr cBlockGlazedTerracottaHandler BlockPurpleGlazedTerracottaHandler(E_BLOCK_PURPLE_GLAZED_TERRACOTTA);
constexpr cDefaultBlockHandler BlockPurpleShulkerBoxHandler (E_BLOCK_PURPLE_SHULKER_BOX);
constexpr cBlockShulkerBoxHandler BlockPurpleShulkerBoxHandler (E_BLOCK_PURPLE_SHULKER_BOX);
constexpr cDefaultBlockHandler BlockPurpurBlockHandler (E_BLOCK_PURPUR_BLOCK);
constexpr cBlockDoubleSlabHandler BlockPurpurDoubleSlabHandler (E_BLOCK_PURPUR_DOUBLE_SLAB);
constexpr cDefaultBlockHandler BlockPurpurPillarHandler (E_BLOCK_PURPUR_PILLAR);
@ -384,7 +385,7 @@ namespace
constexpr cDefaultBlockHandler BlockRedSandstoneHandler (E_BLOCK_RED_SANDSTONE);
constexpr cBlockSlabHandler BlockRedSandstoneSlabHandler (E_BLOCK_RED_SANDSTONE_SLAB);
constexpr cBlockStairsHandler BlockRedSandstoneStairsHandler (E_BLOCK_RED_SANDSTONE_STAIRS);
constexpr cDefaultBlockHandler BlockRedShulkerBoxHandler (E_BLOCK_RED_SHULKER_BOX);
constexpr cBlockShulkerBoxHandler BlockRedShulkerBoxHandler (E_BLOCK_RED_SHULKER_BOX);
constexpr cDefaultBlockHandler BlockRedstoneBlockHandler (E_BLOCK_BLOCK_OF_REDSTONE);
constexpr cBlockRedstoneLampHandler BlockRedstoneLampHandler (E_BLOCK_REDSTONE_LAMP_ON);
constexpr cBlockGlowingRedstoneOreHandler BlockRedstoneOreGlowingHandler (E_BLOCK_REDSTONE_ORE_GLOWING);
@ -438,7 +439,7 @@ namespace
constexpr cBlockWallSignHandler BlockWallsignHandler (E_BLOCK_WALLSIGN);
constexpr cBlockWaterHandler BlockWaterHandler (E_BLOCK_WATER);
constexpr cBlockGlazedTerracottaHandler BlockWhiteGlazedTerracottaHandler (E_BLOCK_WHITE_GLAZED_TERRACOTTA);
constexpr cDefaultBlockHandler BlockWhiteShulkerBoxHandler (E_BLOCK_WHITE_SHULKER_BOX);
constexpr cBlockShulkerBoxHandler BlockWhiteShulkerBoxHandler (E_BLOCK_WHITE_SHULKER_BOX);
constexpr cBlockButtonHandler BlockWoodenButtonHandler (E_BLOCK_WOODEN_BUTTON);
constexpr cBlockPressurePlateHandler BlockWoodenPressurePlateHandler (E_BLOCK_WOODEN_PRESSURE_PLATE);
constexpr cBlockSlabHandler BlockWoodenSlabHandler (E_BLOCK_WOODEN_SLAB);
@ -446,7 +447,7 @@ namespace
constexpr cBlockWorkbenchHandler BlockWorkbenchHandler (E_BLOCK_WORKBENCH);
constexpr cBlockFlowerHandler BlockYellowFlowerHandler (E_BLOCK_YELLOW_FLOWER);
constexpr cBlockGlazedTerracottaHandler BlockYellowGlazedTerracottaHandler(E_BLOCK_YELLOW_GLAZED_TERRACOTTA);
constexpr cDefaultBlockHandler BlockYellowShulkerBoxHandler (E_BLOCK_YELLOW_SHULKER_BOX);
constexpr cBlockShulkerBoxHandler BlockYellowShulkerBoxHandler (E_BLOCK_YELLOW_SHULKER_BOX);
}

View File

@ -0,0 +1,30 @@
#pragma once
#include "../BlockArea.h"
#include "../Entities/Player.h"
#include "BlockHandler.h"
class cBlockShulkerBoxHandler final :
public cBlockEntityHandler
{
public:
using cBlockEntityHandler::cBlockEntityHandler;
private:
virtual bool IsUseable() const override
{
return true;
}
virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override
{
UNUSED(a_BlockMeta);
UNUSED(a_Tool);
return cItem();
}
};

View File

@ -87,6 +87,7 @@ target_sources(
BlockSand.h
BlockSapling.h
BlockSeaLantern.h
BlockShulkerBox.h
BlockSideways.h
BlockSignPost.h
BlockSlab.h

View File

@ -70,6 +70,7 @@ target_sources(
ItemSeeds.h
ItemShears.h
ItemShovel.h
ItemShulkerBox.h
ItemSideways.h
ItemSign.h
ItemSlab.h

View File

@ -73,6 +73,7 @@
#include "ItemSapling.h"
#include "ItemSeeds.h"
#include "ItemShears.h"
#include "ItemShulkerBox.h"
#include "ItemShovel.h"
#include "ItemSideways.h"
#include "ItemSign.h"

135
src/Items/ItemShulkerBox.h Normal file
View File

@ -0,0 +1,135 @@
#pragma once
#include "Items/ItemHandler.h"
#include "BlockInfo.h"
#include "Blocks/BlockShulkerBox.h"
#include "BlockEntities/ShulkerBoxEntity.h"
class cItemShulkerBoxHandler:
public cItemHandler
{
using Super = cItemHandler;
public:
cItemShulkerBoxHandler(int a_ItemType) :
Super(a_ItemType)
{
}
virtual void OnPlayerPlace(
cPlayer & a_Player,
const cItem & a_HeldItem,
Vector3i a_ClickedPosition,
BLOCKTYPE a_ClickedBlockType,
NIBBLETYPE a_ClickedBlockMeta,
eBlockFace a_ClickedBlockFace,
Vector3i a_CursorPosition
) const override
{
if (a_ClickedBlockFace < 0)
{
// Clicked in air
return;
}
if (!cChunkDef::IsValidHeight(a_ClickedPosition))
{
// The clicked block is outside the world, ignore this call altogether (#128)
return;
}
// Check if the block ignores build collision (water, grass etc.):
BLOCKTYPE ClickedBlockType;
NIBBLETYPE ClickedBlockMeta;cChunkInterface ChunkInterface(a_Player.GetWorld()->GetChunkMap());
Vector3i PlacePos;
if (cBlockHandler::For(ClickedBlockType).DoesIgnoreBuildCollision(ChunkInterface, a_ClickedPosition, a_Player, ClickedBlockMeta))
{
PlacePos = a_ClickedPosition;
}
else
{
PlacePos = AddFaceDirection(a_ClickedPosition, a_ClickedBlockFace);
if (!cChunkDef::IsValidHeight(PlacePos))
{
// The block is being placed outside the world, ignore this packet altogether (#128)
return;
}
// Check if the shulker box can overwrite the block at PlacePos:
BLOCKTYPE PlaceBlock;
NIBBLETYPE PlaceMeta;
a_Player.GetWorld()->GetBlockTypeMeta(PlacePos, PlaceBlock, PlaceMeta);
if (!cBlockHandler::For(PlaceBlock).DoesIgnoreBuildCollision(a_Player.GetWorld(), a_Player.GetEquippedItem(), PlacePos, a_Player, PlaceMeta, a_ClickedBlockFace, true))
{
return;
}
}
// Get the meta of the placed shulker box
auto ShulkerBoxType = static_cast<BLOCKTYPE>(m_ItemType);
auto ShulkerBoxMeta = static_cast<NIBBLETYPE>(a_ClickedBlockFace);
// Place the new shulker box:
if (!a_Player.PlaceBlock(PlacePos, ShulkerBoxType, ShulkerBoxMeta))
{
return;
}
a_Player.GetWorld()->DoWithBlockEntityAt(PlacePos, [a_Player, &a_HeldItem](cBlockEntity & a_BlockEntity)
{
switch (a_BlockEntity.GetBlockType())
{
case E_BLOCK_WHITE_SHULKER_BOX:
case E_BLOCK_ORANGE_SHULKER_BOX:
case E_BLOCK_MAGENTA_SHULKER_BOX:
case E_BLOCK_LIGHT_BLUE_SHULKER_BOX:
case E_BLOCK_YELLOW_SHULKER_BOX:
case E_BLOCK_LIME_SHULKER_BOX:
case E_BLOCK_PINK_SHULKER_BOX:
case E_BLOCK_GRAY_SHULKER_BOX:
case E_BLOCK_LIGHT_GRAY_SHULKER_BOX:
case E_BLOCK_CYAN_SHULKER_BOX:
case E_BLOCK_PURPLE_SHULKER_BOX:
case E_BLOCK_BLUE_SHULKER_BOX:
case E_BLOCK_BROWN_SHULKER_BOX:
case E_BLOCK_GREEN_SHULKER_BOX:
case E_BLOCK_RED_SHULKER_BOX:
case E_BLOCK_BLACK_SHULKER_BOX:
{
auto & ShulkerBoxEntity = static_cast<cShulkerBoxEntity &>(a_BlockEntity);
ShulkerBoxEntity.Load(a_HeldItem);
return true;
}
}
});
// Remove the "placed" item from inventory:
if (a_Player.IsGameModeSurvival())
{
a_Player.GetInventory().RemoveOneEquippedItem();
}
return;
}
virtual char GetMaxStackSize(void) const override
{
return 1;
}
private:
cItemShulkerBoxHandler(const cItemShulkerBoxHandler &) = delete;
};

View File

@ -14,6 +14,7 @@ target_sources(
FurnaceWindow.cpp
HopperWindow.cpp
HorseWindow.cpp
ShulkerBoxWindow.cpp
InventoryWindow.cpp
SlotArea.h
@ -29,6 +30,7 @@ target_sources(
FurnaceWindow.h
HopperWindow.h
HorseWindow.h
ShulkerBoxWindow.h
InventoryWindow.h
MinecartWithChestWindow.h
WindowOwner.h

114
src/UI/ShulkerBoxWindow.cpp Normal file
View File

@ -0,0 +1,114 @@
// ShulkerBoxWindow.cpp
// Representing the UI window for the shulker box block
#include "Globals.h"
#include "ShulkerBoxWindow.h"
#include "../BlockEntities/ShulkerBoxEntity.h"
#include "../Entities/Player.h"
#include "SlotArea.h"
#include "../ItemGrid.h"
class cItemGrid;
cShulkerBoxWindow::cShulkerBoxWindow(cShulkerBoxEntity * a_ShulkerBox, const AString & CustomName):
cWindow(wtShulkerBox, CustomName.length() > 0 ? CustomName : "Shulker Box"),
m_World(a_ShulkerBox->GetWorld()),
m_BlockPos(a_ShulkerBox->GetPos()),
m_ShulkerBox(a_ShulkerBox)
{
m_SlotAreas.push_back(new cSlotAreaItemGrid(a_ShulkerBox->GetContents(), *this));
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
// Play the opening sound:
m_World->BroadcastSoundEffect("block.shulker_box.open", m_BlockPos, 1, 1);
// Send out the shulker box open packet:
m_World->BroadcastBlockAction(m_BlockPos, 1, 1, a_ShulkerBox->GetBlockType());
}
cShulkerBoxWindow::~cShulkerBoxWindow()
{
// Send out the shulker box close packet:
m_World->BroadcastBlockAction(m_BlockPos, 1, 0, m_ShulkerBox->GetBlockType());
m_World->BroadcastSoundEffect("block.shulker_box.close", m_BlockPos, 1, 1);
}
bool cShulkerBoxWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse)
{
cWindow::ClosedByPlayer(a_Player, a_CanRefuse);
return true;
}
void cShulkerBoxWindow::OpenedByPlayer(cPlayer & a_Player)
{
m_ShulkerBox->SetNumberOfPlayers(m_ShulkerBox->GetNumberOfPlayers() + 1);
cWindow::OpenedByPlayer(a_Player);
}
void cShulkerBoxWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply)
{
cSlotAreas AreasInOrder;
if (a_ClickedArea == m_SlotAreas[0])
{
// Shulker box Area
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true);
}
else
{
if (cShulkerBoxEntity::IsShulkerBox(a_ItemStack.m_ItemType))
{
return;
}
// Hotbar or Inventory
AreasInOrder.push_back(m_SlotAreas[0]); /* Shulker box */
Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
}
}
void cShulkerBoxWindow::Clicked(cPlayer & a_Player, int a_WindowID, short a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem)
{
if ((a_WindowID == GetWindowID()) && (a_SlotNum >= 0) && (a_SlotNum < m_SlotAreas[0]->GetNumSlots()))
{
cItem & DraggingItem = a_Player.GetDraggingItem();
if (cShulkerBoxEntity::IsShulkerBox(DraggingItem.m_ItemType))
{
return;
}
}
Super::Clicked(a_Player, a_WindowID, a_SlotNum, a_ClickAction, a_ClickedItem);
}

38
src/UI/ShulkerBoxWindow.h Normal file
View File

@ -0,0 +1,38 @@
// ShulkerBoxWindow.h
// Representing the UI window for the shulker box block
#pragma once
#include "Window.h"
#include "../BlockEntities/ShulkerBoxEntity.h"
class cShulkerBoxWindow :
public cWindow
{
using Super = cWindow;
public:
cShulkerBoxWindow(cShulkerBoxEntity * a_ShulkerBox, const AString & CustomName);
virtual ~cShulkerBoxWindow() override;
virtual bool ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) override;
virtual void OpenedByPlayer(cPlayer & a_Player) override;
virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override;
virtual void Clicked(cPlayer & a_Player, int a_WindowID, short a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override;
protected:
cWorld * m_World;
Vector3i m_BlockPos; // Position of the shulker, for the window-close packet
cShulkerBoxEntity * m_ShulkerBox;
};

View File

@ -75,6 +75,7 @@ const AString cWindow::GetWindowTypeName(void) const
case wtHopper: return "minecraft:hopper";
case wtDropper: return "minecraft:dropper";
case wtAnimalChest: return "EntityHorse";
case wtShulkerBox: return "minecraft:shulker_box";
default:
{
ASSERT(!"Unknown inventory type!");

View File

@ -68,6 +68,7 @@ public:
wtHopper = 9,
wtDropper = 10,
wtAnimalChest = 11,
wtShulkerBox = 12,
};
// tolua_end

View File

@ -31,6 +31,7 @@
#include "../BlockEntities/SignEntity.h"
#include "../BlockEntities/MobHeadEntity.h"
#include "../BlockEntities/FlowerPotEntity.h"
#include "../BlockEntities/ShulkerBoxEntity.h"
#include "../Entities/Entity.h"
#include "../Entities/EnderCrystal.h"
@ -608,6 +609,21 @@ public:
void AddShulkerBoxEntity(cShulkerBoxEntity * a_ShulkerBox)
{
mWriter.BeginCompound("");
AddBasicTileEntity(a_ShulkerBox, "ShulkerBox");
mWriter.BeginList("Items", TAG_Compound);
AddItemGrid(a_ShulkerBox->GetContents());
mWriter.EndList();
mWriter.AddString("CustomName", a_ShulkerBox->m_CustomName);
mWriter.EndCompound();
}
void AddMobHeadEntity(cMobHeadEntity * a_MobHead)
{
mWriter.BeginCompound("");

View File

@ -33,6 +33,7 @@
#include "../BlockEntities/MobHeadEntity.h"
#include "../BlockEntities/MobSpawnerEntity.h"
#include "../BlockEntities/FlowerPotEntity.h"
#include "../BlockEntities/ShulkerBoxEntity.h"
#include "../Mobs/IncludeAllMonsters.h"
@ -650,6 +651,24 @@ OwnedBlockEntity cWSSAnvil::LoadBlockEntityFromNBT(const cParsedNBT & a_NBT, int
case E_BLOCK_NOTE_BLOCK: return LoadNoteBlockFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos);
case E_BLOCK_SIGN_POST: return LoadSignFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos);
case E_BLOCK_TRAPPED_CHEST: return LoadChestFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos);
case E_BLOCK_WHITE_SHULKER_BOX:
case E_BLOCK_ORANGE_SHULKER_BOX:
case E_BLOCK_MAGENTA_SHULKER_BOX:
case E_BLOCK_LIGHT_BLUE_SHULKER_BOX:
case E_BLOCK_YELLOW_SHULKER_BOX:
case E_BLOCK_LIME_SHULKER_BOX:
case E_BLOCK_PINK_SHULKER_BOX:
case E_BLOCK_GRAY_SHULKER_BOX:
case E_BLOCK_LIGHT_GRAY_SHULKER_BOX:
case E_BLOCK_CYAN_SHULKER_BOX:
case E_BLOCK_PURPLE_SHULKER_BOX:
case E_BLOCK_BLUE_SHULKER_BOX:
case E_BLOCK_BROWN_SHULKER_BOX:
case E_BLOCK_GREEN_SHULKER_BOX:
case E_BLOCK_RED_SHULKER_BOX:
case E_BLOCK_BLACK_SHULKER_BOX: return LoadShulkerBoxFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos);
case E_BLOCK_WALLSIGN: return LoadSignFromNBT (a_NBT, a_Tag, a_BlockType, a_BlockMeta, a_Pos);
default:
{
@ -1518,6 +1537,37 @@ OwnedBlockEntity cWSSAnvil::LoadNoteBlockFromNBT(const cParsedNBT & a_NBT, int a
OwnedBlockEntity cWSSAnvil::LoadShulkerBoxFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos)
{
// Check if the data has a proper type:
static const AStringVector expectedTypes({"ShulkerBox", "minecraft:shulker_box"});
if (!CheckBlockEntityType(a_NBT, a_TagIdx, expectedTypes, a_Pos))
{
return nullptr;
}
int Items = a_NBT.FindChildByName(a_TagIdx, "Items");
if ((Items < 0) || (a_NBT.GetType(Items) != TAG_List))
{
return nullptr;
}
auto ShulkerBox = std::make_unique<cShulkerBoxEntity>(a_BlockType, a_BlockMeta, a_Pos, m_World);
LoadItemGridFromNBT(ShulkerBox->GetContents(), a_NBT, Items);
int CustomName = a_NBT.FindChildByName(a_TagIdx, "CustomName");
if ((CustomName > 0) || (a_NBT.GetType(CustomName) == TAG_String))
{
ShulkerBox->m_CustomName = a_NBT.GetString(CustomName);
}
return ShulkerBox;
}
OwnedBlockEntity cWSSAnvil::LoadSignFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos)
{
// Check if the data has a proper type:

View File

@ -168,6 +168,7 @@ protected:
OwnedBlockEntity LoadMobHeadFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos);
OwnedBlockEntity LoadMobSpawnerFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos);
OwnedBlockEntity LoadNoteBlockFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos);
OwnedBlockEntity LoadShulkerBoxFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos);
OwnedBlockEntity LoadSignFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos);
void LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, std::string_view a_EntityName);