mirror of
https://github.com/cuberite/cuberite.git
synced 2025-01-08 11:57:39 +08:00
Merged viable code from #5120
This commit is contained in:
parent
ebeb164d2b
commit
973d30703b
@ -13415,6 +13415,10 @@ end
|
||||
{
|
||||
Notes = "A villager trade window",
|
||||
},
|
||||
wtShulkerBox =
|
||||
{
|
||||
Notes = "A shulker box window",
|
||||
},
|
||||
wtWorkbench =
|
||||
{
|
||||
Notes = "A workbench (crafting table) window",
|
||||
|
@ -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 = [[
|
||||
|
@ -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 =
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
)
|
||||
|
229
src/BlockEntities/ShulkerBoxEntity.cpp
Normal file
229
src/BlockEntities/ShulkerBoxEntity.cpp
Normal 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);
|
||||
}
|
78
src/BlockEntities/ShulkerBoxEntity.h
Normal file
78
src/BlockEntities/ShulkerBoxEntity.h
Normal 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
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
30
src/Blocks/BlockShulkerBox.h
Normal file
30
src/Blocks/BlockShulkerBox.h
Normal 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();
|
||||
}
|
||||
};
|
@ -87,6 +87,7 @@ target_sources(
|
||||
BlockSand.h
|
||||
BlockSapling.h
|
||||
BlockSeaLantern.h
|
||||
BlockShulkerBox.h
|
||||
BlockSideways.h
|
||||
BlockSignPost.h
|
||||
BlockSlab.h
|
||||
|
@ -70,6 +70,7 @@ target_sources(
|
||||
ItemSeeds.h
|
||||
ItemShears.h
|
||||
ItemShovel.h
|
||||
ItemShulkerBox.h
|
||||
ItemSideways.h
|
||||
ItemSign.h
|
||||
ItemSlab.h
|
||||
|
@ -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
135
src/Items/ItemShulkerBox.h
Normal 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;
|
||||
};
|
@ -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
114
src/UI/ShulkerBoxWindow.cpp
Normal 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
38
src/UI/ShulkerBoxWindow.h
Normal 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;
|
||||
};
|
@ -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!");
|
||||
|
@ -68,6 +68,7 @@ public:
|
||||
wtHopper = 9,
|
||||
wtDropper = 10,
|
||||
wtAnimalChest = 11,
|
||||
wtShulkerBox = 12,
|
||||
};
|
||||
|
||||
// tolua_end
|
||||
|
@ -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("");
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user