Added basic ender chests
Note that they just mirror chests now, so no per player inventory.
This commit is contained in:
parent
30ead79049
commit
347e80bdd8
@ -224,6 +224,7 @@
|
||||
<ResourceCompile Include="MCServer.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\src\BlockEntities\EnderChestEntity.h" />
|
||||
<ClInclude Include="resource_MCServer.h" />
|
||||
<ClInclude Include="..\src\Authenticator.h" />
|
||||
<ClInclude Include="..\src\BlockArea.h" />
|
||||
@ -615,6 +616,7 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\src\Authenticator.cpp" />
|
||||
<ClCompile Include="..\src\BlockArea.cpp" />
|
||||
<ClCompile Include="..\src\BlockEntities\EnderChestEntity.cpp" />
|
||||
<ClCompile Include="..\src\BlockID.cpp" />
|
||||
<ClCompile Include="..\src\BoundingBox.cpp" />
|
||||
<ClCompile Include="..\src\ByteBuffer.cpp" />
|
||||
|
@ -945,6 +945,9 @@
|
||||
<ClInclude Include="..\src\HTTPServer\NameValueParser.h">
|
||||
<Filter>Source Files\HTTPServer</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\BlockEntities\EnderChestEntity.h">
|
||||
<Filter>Source Files\BlockEntities</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\webadmin\template.html">
|
||||
@ -1654,6 +1657,9 @@
|
||||
<ClCompile Include="..\src\HTTPServer\NameValueParser.cpp">
|
||||
<Filter>Source Files\HTTPServer</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\BlockEntities\EnderChestEntity.cpp">
|
||||
<Filter>Source Files\BlockEntities</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\MCServer\API.txt">
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "ChestEntity.h"
|
||||
#include "DispenserEntity.h"
|
||||
#include "DropperEntity.h"
|
||||
#include "EnderChestEntity.h"
|
||||
#include "FurnaceEntity.h"
|
||||
#include "HopperEntity.h"
|
||||
#include "JukeboxEntity.h"
|
||||
@ -22,16 +23,17 @@ cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE
|
||||
{
|
||||
switch (a_BlockType)
|
||||
{
|
||||
case E_BLOCK_CHEST: return new cChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_DISPENSER: return new cDispenserEntity(a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_DROPPER: return new cDropperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
|
||||
case E_BLOCK_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
|
||||
case E_BLOCK_HOPPER: return new cHopperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_SIGN_POST: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_WALLSIGN: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_NOTE_BLOCK: return new cNoteEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_JUKEBOX: return new cJukeboxEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_CHEST: return new cChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_DISPENSER: return new cDispenserEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_DROPPER: return new cDropperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_ENDER_CHEST: return new cEnderChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
|
||||
case E_BLOCK_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
|
||||
case E_BLOCK_HOPPER: return new cHopperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_SIGN_POST: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_WALLSIGN: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_NOTE_BLOCK: return new cNoteEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_JUKEBOX: return new cJukeboxEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
}
|
||||
LOGD("%s: Requesting creation of an unknown block entity - block type %d (%s)",
|
||||
__FUNCTION__, a_BlockType, ItemTypeToString(a_BlockType).c_str()
|
||||
|
130
src/BlockEntities/EnderChestEntity.cpp
Normal file
130
src/BlockEntities/EnderChestEntity.cpp
Normal file
@ -0,0 +1,130 @@
|
||||
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "EnderChestEntity.h"
|
||||
#include "../Item.h"
|
||||
#include "../Entities/Player.h"
|
||||
#include "../UI/Window.h"
|
||||
#include "json/json.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cEnderChestEntity::cEnderChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
|
||||
super(E_BLOCK_ENDER_CHEST, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World)
|
||||
{
|
||||
cBlockEntityWindowOwner::SetBlockEntity(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cEnderChestEntity::~cEnderChestEntity()
|
||||
{
|
||||
cWindow * Window = GetWindow();
|
||||
if (Window != NULL)
|
||||
{
|
||||
Window->OwnerDestroyed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cEnderChestEntity::LoadFromJson(const Json::Value & a_Value)
|
||||
{
|
||||
m_PosX = a_Value.get("x", 0).asInt();
|
||||
m_PosY = a_Value.get("y", 0).asInt();
|
||||
m_PosZ = a_Value.get("z", 0).asInt();
|
||||
|
||||
Json::Value AllSlots = a_Value.get("Slots", 0);
|
||||
int SlotIdx = 0;
|
||||
for (Json::Value::iterator itr = AllSlots.begin(); itr != AllSlots.end(); ++itr)
|
||||
{
|
||||
cItem Item;
|
||||
Item.FromJson(*itr);
|
||||
SetSlot(SlotIdx, Item);
|
||||
SlotIdx++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cEnderChestEntity::SaveToJson(Json::Value & a_Value)
|
||||
{
|
||||
a_Value["x"] = m_PosX;
|
||||
a_Value["y"] = m_PosY;
|
||||
a_Value["z"] = m_PosZ;
|
||||
|
||||
Json::Value AllSlots;
|
||||
for (int i = m_Contents.GetNumSlots() - 1; i >= 0; i--)
|
||||
{
|
||||
Json::Value Slot;
|
||||
m_Contents.GetSlot(i).GetJson(Slot);
|
||||
AllSlots.append(Slot);
|
||||
}
|
||||
a_Value["Slots"] = AllSlots;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cEnderChestEntity::SendTo(cClientHandle & a_Client)
|
||||
{
|
||||
// The chest entity doesn't need anything sent to the client when it's created / gets in the viewdistance
|
||||
// All the actual handling is in the cWindow UI code that gets called when the chest is rclked
|
||||
|
||||
UNUSED(a_Client);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cEnderChestEntity::UsedBy(cPlayer * a_Player)
|
||||
{
|
||||
// If the window is not created, open it anew:
|
||||
cWindow * Window = GetWindow();
|
||||
if (Window == NULL)
|
||||
{
|
||||
OpenNewWindow();
|
||||
Window = GetWindow();
|
||||
}
|
||||
|
||||
// Open the window for the player:
|
||||
if (Window != NULL)
|
||||
{
|
||||
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
|
||||
int ChunkX, ChunkZ;
|
||||
cChunkDef::BlockToChunk(m_PosX, m_PosZ, ChunkX, ChunkZ);
|
||||
m_World->MarkChunkDirty(ChunkX, ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cEnderChestEntity::OpenNewWindow(void)
|
||||
{
|
||||
OpenWindow(new cEnderChestWindow(this));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
59
src/BlockEntities/EnderChestEntity.h
Normal file
59
src/BlockEntities/EnderChestEntity.h
Normal file
@ -0,0 +1,59 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BlockEntityWithItems.h"
|
||||
#include "../UI/WindowOwner.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace Json
|
||||
{
|
||||
class Value;
|
||||
};
|
||||
|
||||
class cClientHandle;
|
||||
class cServer;
|
||||
class cNBTData;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cEnderChestEntity : // tolua_export
|
||||
public cBlockEntityWindowOwner,
|
||||
// tolua_begin
|
||||
public cBlockEntityWithItems
|
||||
{
|
||||
typedef cBlockEntityWithItems super;
|
||||
|
||||
public:
|
||||
enum {
|
||||
ContentsHeight = 3,
|
||||
ContentsWidth = 9,
|
||||
} ;
|
||||
|
||||
// tolua_end
|
||||
|
||||
/// Constructor used for normal operation
|
||||
cEnderChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
|
||||
|
||||
virtual ~cEnderChestEntity();
|
||||
|
||||
static const char * GetClassStatic(void) { return "cEnderChestEntity"; }
|
||||
|
||||
bool LoadFromJson(const Json::Value & a_Value);
|
||||
|
||||
// cBlockEntity overrides:
|
||||
virtual void SaveToJson(Json::Value & a_Value) override;
|
||||
virtual void SendTo(cClientHandle & a_Client) override;
|
||||
virtual void UsedBy(cPlayer * a_Player) override;
|
||||
|
||||
/// Opens a new chest window for this chest. Scans for neighbors to open a double chest window, if appropriate.
|
||||
void OpenNewWindow(void);
|
||||
} ; // tolua_export
|
||||
|
||||
|
||||
|
||||
|
@ -1,18 +1,18 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "BlockEntity.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cBlockEnderchestHandler :
|
||||
public cBlockHandler
|
||||
public cBlockEntityHandler
|
||||
{
|
||||
public:
|
||||
cBlockEnderchestHandler(BLOCKTYPE a_BlockType)
|
||||
: cBlockHandler(a_BlockType)
|
||||
: cBlockEntityHandler(a_BlockType)
|
||||
{
|
||||
}
|
||||
|
||||
@ -21,6 +21,49 @@ public:
|
||||
//todo: Drop Ender Chest if using silk touch pickaxe
|
||||
a_Pickups.push_back(cItem(E_BLOCK_OBSIDIAN, 8, 0));
|
||||
}
|
||||
|
||||
virtual bool GetPlacementBlockTypeMeta(
|
||||
cWorld * a_World, cPlayer * a_Player,
|
||||
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
|
||||
int a_CursorX, int a_CursorY, int a_CursorZ,
|
||||
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
|
||||
) override
|
||||
{
|
||||
a_BlockType = m_BlockType;
|
||||
a_BlockMeta = RotationToMetaData(a_Player->GetRotation());
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual const char * GetStepSound(void) override
|
||||
{
|
||||
return "step.stone";
|
||||
}
|
||||
|
||||
static NIBBLETYPE RotationToMetaData(double a_Rotation)
|
||||
{
|
||||
a_Rotation += 90 + 45; // So its not aligned with axis
|
||||
|
||||
if (a_Rotation > 360.f)
|
||||
{
|
||||
a_Rotation -= 360.f;
|
||||
}
|
||||
if ((a_Rotation >= 0.f) && (a_Rotation < 90.f))
|
||||
{
|
||||
return 0x4;
|
||||
}
|
||||
else if ((a_Rotation >= 180) && (a_Rotation < 270))
|
||||
{
|
||||
return 0x5;
|
||||
}
|
||||
else if ((a_Rotation >= 90) && (a_Rotation < 180))
|
||||
{
|
||||
return 0x2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0x3;
|
||||
}
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "BlockEntity.h"
|
||||
#include "../World.h"
|
||||
#include "../Piston.h"
|
||||
#include "../Entities/Player.h"
|
||||
|
||||
|
||||
|
||||
|
@ -1301,6 +1301,7 @@ void cChunk::CreateBlockEntities(void)
|
||||
case E_BLOCK_CHEST:
|
||||
case E_BLOCK_DISPENSER:
|
||||
case E_BLOCK_DROPPER:
|
||||
case E_BLOCK_ENDER_CHEST:
|
||||
case E_BLOCK_LIT_FURNACE:
|
||||
case E_BLOCK_FURNACE:
|
||||
case E_BLOCK_HOPPER:
|
||||
@ -1413,6 +1414,7 @@ void cChunk::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType,
|
||||
case E_BLOCK_CHEST:
|
||||
case E_BLOCK_DISPENSER:
|
||||
case E_BLOCK_DROPPER:
|
||||
case E_BLOCK_ENDER_CHEST:
|
||||
case E_BLOCK_LIT_FURNACE:
|
||||
case E_BLOCK_FURNACE:
|
||||
case E_BLOCK_HOPPER:
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "../Entities/Player.h"
|
||||
#include "../BlockEntities/ChestEntity.h"
|
||||
#include "../BlockEntities/DropSpenserEntity.h"
|
||||
#include "../BlockEntities/EnderChestEntity.h"
|
||||
#include "../BlockEntities/FurnaceEntity.h"
|
||||
#include "../Items/ItemHandler.h"
|
||||
#include "Window.h"
|
||||
@ -556,6 +557,38 @@ cCraftingRecipe & cSlotAreaCrafting::GetRecipeForPlayer(cPlayer & a_Player)
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cSlotAreaEnderChest:
|
||||
|
||||
cSlotAreaEnderChest::cSlotAreaEnderChest(cEnderChestEntity * a_EnderChest, cWindow & a_ParentWindow) :
|
||||
cSlotArea(27, a_ParentWindow),
|
||||
m_EnderChest(a_EnderChest)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const cItem * cSlotAreaEnderChest::GetSlot(int a_SlotNum, cPlayer & a_Player) const
|
||||
{
|
||||
// a_SlotNum ranges from 0 to 26, use that to index the chest entity's inventory directly:
|
||||
return &(m_EnderChest->GetSlot(a_SlotNum));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cSlotAreaEnderChest::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item)
|
||||
{
|
||||
m_EnderChest->SetSlot(a_SlotNum, a_Item);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cSlotAreaFurnace:
|
||||
|
||||
|
@ -16,6 +16,7 @@ class cWindow;
|
||||
class cPlayer;
|
||||
class cChestEntity;
|
||||
class cDropSpenserEntity;
|
||||
class cEnderChestEntity;
|
||||
class cFurnaceEntity;
|
||||
class cCraftingRecipe;
|
||||
|
||||
@ -286,6 +287,23 @@ protected:
|
||||
|
||||
|
||||
|
||||
class cSlotAreaEnderChest :
|
||||
public cSlotArea
|
||||
{
|
||||
public:
|
||||
cSlotAreaEnderChest(cEnderChestEntity * a_EnderChest, cWindow & a_ParentWindow);
|
||||
|
||||
virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override;
|
||||
virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override;
|
||||
|
||||
protected:
|
||||
cEnderChestEntity * m_EnderChest;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cSlotAreaFurnace :
|
||||
public cSlotArea,
|
||||
public cItemGrid::cListener
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "../Items/ItemHandler.h"
|
||||
#include "../BlockEntities/ChestEntity.h"
|
||||
#include "../BlockEntities/DropSpenserEntity.h"
|
||||
#include "../BlockEntities/EnderChestEntity.h"
|
||||
#include "../BlockEntities/HopperEntity.h"
|
||||
|
||||
|
||||
@ -853,6 +854,43 @@ cDropSpenserWindow::cDropSpenserWindow(int a_BlockX, int a_BlockY, int a_BlockZ,
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cEnderChestWindow:
|
||||
|
||||
cEnderChestWindow::cEnderChestWindow(cEnderChestEntity * a_EnderChest) :
|
||||
cWindow(wtChest, "Ender Chest"),
|
||||
m_World(a_EnderChest->GetWorld()),
|
||||
m_BlockX(a_EnderChest->GetPosX()),
|
||||
m_BlockY(a_EnderChest->GetPosY()),
|
||||
m_BlockZ(a_EnderChest->GetPosZ())
|
||||
{
|
||||
m_SlotAreas.push_back(new cSlotAreaEnderChest(a_EnderChest, *this));
|
||||
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
|
||||
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
|
||||
|
||||
// Play the opening sound:
|
||||
m_World->BroadcastSoundEffect("random.chestopen", m_BlockX * 8, m_BlockY * 8, m_BlockZ * 8, 1, 1);
|
||||
|
||||
// Send out the chest-open packet:
|
||||
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, E_BLOCK_ENDER_CHEST);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cEnderChestWindow::~cEnderChestWindow()
|
||||
{
|
||||
// Send out the chest-close packet:
|
||||
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 0, E_BLOCK_ENDER_CHEST);
|
||||
|
||||
m_World->BroadcastSoundEffect("random.chestclosed", m_BlockX * 8, m_BlockY * 8, m_BlockZ * 8, 1, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cHopperWindow:
|
||||
|
||||
|
@ -20,6 +20,7 @@ class cWindowOwner;
|
||||
class cClientHandle;
|
||||
class cChestEntity;
|
||||
class cDropSpenserEntity;
|
||||
class cEnderChestEntity;
|
||||
class cFurnaceEntity;
|
||||
class cHopperEntity;
|
||||
class cSlotArea;
|
||||
@ -283,6 +284,22 @@ protected:
|
||||
|
||||
|
||||
|
||||
class cEnderChestWindow :
|
||||
public cWindow
|
||||
{
|
||||
public:
|
||||
cEnderChestWindow(cEnderChestEntity * a_EnderChest);
|
||||
~cEnderChestWindow();
|
||||
|
||||
protected:
|
||||
cWorld * m_World;
|
||||
int m_BlockX, m_BlockY, m_BlockZ; // Position of the enderchest, for the window-close packet
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cInventoryWindow :
|
||||
public cWindow
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user