1
0

A bit of cleanup and documentation around the UI window handling

git-svn-id: http://mc-server.googlecode.com/svn/trunk@716 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
madmaxoft@gmail.com 2012-08-06 20:10:16 +00:00
parent 0b4a84969c
commit e8366993ce
13 changed files with 143 additions and 86 deletions

View File

@ -27,21 +27,30 @@ public:
virtual NIBBLETYPE GetDropMeta(NIBBLETYPE a_BlockMeta);
virtual bool NeedsRandomTicks();
virtual void DropBlock(cWorld *a_World, int a_X, int a_Y, int a_Z);
//Checks if the block can stay at
virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z);
//Checks if the block can be placed at this point. Default: CanBeAt(...) NOTE: In the block is not placed in this callback
virtual bool CanBePlacedAt(cWorld *a_World, int a_X, int a_Y, int a_Z, char a_Dir);
//This gets called if the player tries to place a block ontop of this block (Only if he aims directly on this block)
virtual bool AllowBlockOnTop();
virtual bool IsUseable();
virtual bool IsClickedThrough();
virtual bool IgnoreBuildCollision();
//Indicates this block can be placed on the side of other blocks. Default: true
/// Checks if the block can stay at the specified coords in the
virtual bool CanBeAt(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ);
/// Checks if the block can be placed at this point. Default: CanBeAt(...) NOTE: This call doesn't actually place the block
virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir);
/// Called when the player tries to place a block on top of this block (Only if he aims directly on this block); return false to disallow
virtual bool AllowBlockOnTop(void);
/// Called to check whether this block supports a rclk action. If it returns true, OnClicked() is called
virtual bool IsUseable(void);
virtual bool IsClickedThrough(void);
virtual bool IgnoreBuildCollision(void);
/// Indicates this block can be placed on the side of other blocks. Default: true
virtual bool CanBePlacedOnSide();
//Does this block drops if it gets destroyed by an unsuitable situation? Default: true
/// Does this block drop if it gets destroyed by an unsuitable situation? Default: true
virtual bool DropOnUnsuitable();
static cBlockHandler *GetBlockHandler(BLOCKTYPE a_BlockID);
static cBlockHandler * GetBlockHandler(BLOCKTYPE a_BlockID);
static void Deinit();

View File

@ -1,7 +1,12 @@
#pragma once
#include "Block.h"
class cBlockEntityHandler : public cBlockHandler
{
public:
@ -9,14 +14,18 @@ public:
: cBlockHandler(a_BlockID)
{
}
virtual void OnClick(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z) override
virtual void OnClick(cWorld * a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override
{
a_World->UseBlockEntity(a_Player, a_X, a_Y, a_Z);
a_World->UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ);
}
virtual bool IsUseable() override
{
return true;
}
};
};

View File

@ -157,8 +157,8 @@ void cChestEntity::SaveToJson( Json::Value& a_Value )
void cChestEntity::SendTo( cClientHandle* a_Client, cServer* a_Server )
{
(void)a_Client;
(void)a_Server;
UNUSED(a_Client);
UNUSED(a_Server);
return;
}
@ -166,14 +166,12 @@ void cChestEntity::SendTo( cClientHandle* a_Client, cServer* a_Server )
void cChestEntity::UsedBy( cPlayer * a_Player )
void cChestEntity::UsedBy(cPlayer * a_Player)
{
if( !GetWindow() )
if (!GetWindow())
{
cWindow* Window = new cWindow( this, true );
Window->SetSlots( GetContents(), GetChestHeight()*c_ChestWidth );
Window->SetWindowID( 1 );
Window->SetWindowType( cWindow::Chest );
cWindow * Window = new cWindow(this, true, cWindow::Chest, 1);
Window->SetSlots(GetContents(), GetChestHeight() * c_ChestWidth);
Window->SetWindowTitle("UberChest");
Window->GetOwner()->SetEntity(this);
OpenWindow( Window );

View File

@ -262,18 +262,18 @@ void cChunkMap::BroadcastToChunkOfBlock(int a_X, int a_Y, int a_Z, const cPacket
void cChunkMap::UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z)
void cChunkMap::UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// a_Player rclked block entity at the coords specified, handle it
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(a_X, a_Y, a_Z, ChunkX, ChunkZ);
cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
return;
}
Chunk->UseBlockEntity(a_Player, a_X, a_Y, a_Z);
Chunk->UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ);
}

View File

@ -882,10 +882,12 @@ void cClientHandle::HandleBlockPlace(cPacket_BlockPlace * a_Packet)
cWorld * World = m_Player->GetWorld();
cBlockHandler *Handler = cBlockHandler::GetBlockHandler(World->GetBlock(a_Packet->m_PosX, a_Packet->m_PosY, a_Packet->m_PosZ));
if(Handler->IsUseable())
if (Handler->IsUseable())
{
Handler->OnClick(World, m_Player, a_Packet->m_PosX, a_Packet->m_PosY, a_Packet->m_PosZ);
}else{
}
else
{
cItemHandler *ItemHandler = cItemHandler::GetItemHandler(Equipped.m_ItemID);
if(ItemHandler->OnItemUse(World, m_Player, &Equipped, a_Packet->m_PosX, a_Packet->m_PosY, a_Packet->m_PosZ, a_Packet->m_Direction))

View File

@ -19,12 +19,9 @@
cCraftingWindow::cCraftingWindow( cWindowOwner* a_Owner, bool a_bInventoryVisible )
: cWindow( a_Owner, a_bInventoryVisible )
: cWindow(a_Owner, a_bInventoryVisible, cWindow::Workbench, 1)
{
SetWindowID( 1 );
SetWindowType( cWindow::Workbench ); // Workbench
cItem* Slots = new cItem[10];
cItem * Slots = new cItem[10];
SetSlots( Slots, 10 );
}

View File

@ -13,21 +13,23 @@
cFurnaceWindow::cFurnaceWindow( cFurnaceEntity* a_Owner )
: cWindow( a_Owner, true )
: cWindow(a_Owner, true, cWindow::Furnace, 1)
, m_Furnace( a_Owner )
{
SetWindowID( 1 );
SetWindowType( cWindow::Furnace ); // Furnace
}
void cFurnaceWindow::Clicked( cPacket_WindowClick* a_ClickPacket, cPlayer & a_Player )
void cFurnaceWindow::Clicked(cPacket_WindowClick * a_ClickPacket, cPlayer & a_Player)
{
cItem Fuel = *GetSlot( 0 );
cWindow::Clicked( a_ClickPacket, a_Player );
if( m_Furnace )
if (m_Furnace != NULL)
{
if( a_ClickPacket->m_SlotNum >= 0 && a_ClickPacket->m_SlotNum <= 2 ) // them important slots
if ((a_ClickPacket->m_SlotNum >= 0) && (a_ClickPacket->m_SlotNum <= 2)) // them important slots
{
if( Fuel.m_ItemID != GetSlot( 0 )->m_ItemID )
m_Furnace->ResetCookTimer();
@ -40,8 +42,16 @@ void cFurnaceWindow::Clicked( cPacket_WindowClick* a_ClickPacket, cPlayer & a_Pl
}
}
void cFurnaceWindow::Close( cPlayer & a_Player )
{
m_Furnace = 0;
m_Furnace = NULL;
cWindow::Close( a_Player );
}
}

View File

@ -48,10 +48,9 @@ cInventory::cInventory(cPlayer* a_Owner)
if( !GetWindow() )
{
cWindow* Window = new cWindow( this, false );
Window->SetSlots( m_Slots, c_NumSlots );
Window->SetWindowID( 0 );
OpenWindow( Window );
cWindow* Window = new cWindow( this, false, cWindow::Inventory, 0);
Window->SetSlots(m_Slots, c_NumSlots);
OpenWindow(Window);
}
}

View File

@ -460,7 +460,7 @@ void cPlayer::CloseWindow(char a_WindowType)
(m_Inventory->GetWindow()->GetDraggingItem()->m_ItemCount > 0)
)
{
LOG("Player holds item! Dropping it...");
LOGD("Player holds item! Dropping it...");
TossItem( true, m_Inventory->GetWindow()->GetDraggingItem()->m_ItemCount );
}
@ -481,17 +481,18 @@ void cPlayer::CloseWindow(char a_WindowType)
m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY() + 1.6f, GetPosZ(), vX * 2, vY * 2, vZ * 2);
}
if (m_CurrentWindow)
if (m_CurrentWindow != NULL)
{
// FIXME: If the player entity is destroyed while having a chest window open, the chest will not close
if (a_WindowType == 1 && strcmp(m_CurrentWindow->GetWindowTitle().c_str(), "UberChest") == 0) { // Chest
cBlockEntity *block = m_CurrentWindow->GetOwner()->GetEntity();
if ((a_WindowType == 1) && (m_CurrentWindow->GetWindowType() == cWindow::Chest))
{
// Chest
cPacket_BlockAction ChestClose;
ChestClose.m_PosX = block->GetPosX();
ChestClose.m_PosY = (short)block->GetPosY();
ChestClose.m_PosZ = block->GetPosZ();
ChestClose.m_Byte1 = 1;
ChestClose.m_Byte2 = 0;
int y = 0;
m_CurrentWindow->GetOwner()->GetBlockPos(ChestClose.m_PosX, y, ChestClose.m_PosZ);
ChestClose.m_PosY = (short)y;
ChestClose.m_Byte1 = 1; // Unused, always 1
ChestClose.m_Byte2 = 0; // 0 = closed
m_World->Broadcast(ChestClose);
}

View File

@ -18,9 +18,9 @@
cWindow::cWindow( cWindowOwner* a_Owner, bool a_bInventoryVisible )
: m_WindowID( 0 )
, m_WindowType( 0 )
cWindow::cWindow( cWindowOwner* a_Owner, bool a_bInventoryVisible, cWindow::WindowType a_WindowType, int a_WindowID)
: m_WindowID( a_WindowID )
, m_WindowType( a_WindowType )
, m_Owner( a_Owner )
, m_bInventoryVisible( a_bInventoryVisible )
, m_NumSlots( 0 )
@ -28,8 +28,11 @@ cWindow::cWindow( cWindowOwner* a_Owner, bool a_bInventoryVisible )
, m_DraggingItem( 0 )
, m_IsDestroyed(false)
{
LOGD("Created a window at %p", this);
if( !m_bInventoryVisible ) m_DraggingItem = new cItem();
LOGD("Created a window at %p, type = %d, ID = %i", this, a_WindowType, a_WindowID);
if (!m_bInventoryVisible)
{
m_DraggingItem = new cItem();
}
}
@ -234,18 +237,18 @@ void cWindow::Open( cPlayer & a_Player )
void cWindow::Close( cPlayer & a_Player )
{
//Checks wheather the player is still holding an item
if(m_DraggingItem && m_DraggingItem->m_ItemCount > 0)
if (m_DraggingItem && m_DraggingItem->m_ItemCount > 0)
{
LOG("Player holds item! Dropping it...");
a_Player.TossItem( true, m_DraggingItem->m_ItemCount );
LOGD("Player holds item! Dropping it...");
a_Player.TossItem(true, m_DraggingItem->m_ItemCount);
}
cPacket_WindowClose WindowClose;
WindowClose.m_Close = (char)m_WindowID;
cClientHandle * ClientHandle = a_Player.GetClientHandle();
if ( ClientHandle != NULL)
if (ClientHandle != NULL)
{
ClientHandle->Send( WindowClose );
ClientHandle->Send(WindowClose);
}
{

View File

@ -1,3 +1,12 @@
// cWindow.h
// Interfaces to the cWindow class representing a UI window for a specific block
#pragma once
@ -14,26 +23,32 @@ typedef std::list<cPlayer *> cPlayerList;
/**
Represents a UI window (base class) for a specific block entity.
There is up to one instance of the class for each block entity
Each window has a list of players that are currently using it
When there's no player using a window, it is destroyed
*/
class cWindow
{
public:
cWindow( cWindowOwner* a_Owner, bool a_bInventoryVisible );
enum WindowType
{
Inventory = -1, // This value is never actually sent to a client
Chest = 0,
Workbench = 1,
Furnace = 2,
Dispenser = 3,
Enchantment = 4,
Brewery = 5
};
cWindow(cWindowOwner * a_Owner, bool a_bInventoryVisible, WindowType a_WindowType, int a_WindowID);
~cWindow();
int GetWindowID() { return m_WindowID; }
void SetWindowID( int a_WindowID ) { m_WindowID = a_WindowID; }
enum WindowType {
Chest,
Workbench,
Furnace,
Dispenser,
Enchantment,
Brewery
};
int GetWindowType() { return m_WindowType; }
void SetWindowType( int a_WindowType ) { m_WindowType = a_WindowType; }
int GetWindowType(void) const { return m_WindowType; }
cItem* GetSlots() { return m_Slots; }
int GetNumSlots() { return m_NumSlots; }

View File

@ -1,13 +1,21 @@
#pragma once
#include "cBlockEntity.h"
class cWindow;
class cBlockEntity;
/**
Implements the base behavior expected from a class that can handle UI windows for block entities.
*/
class cWindowOwner
{
public:
@ -17,11 +25,17 @@ public:
cWindow* GetWindow() { return m_Window; }
void SetEntity(cBlockEntity *a_Entity) { m_Entity = a_Entity; }
cBlockEntity *GetEntity() { return m_Entity; }
void SetEntity(cBlockEntity * a_Entity) { m_Entity = a_Entity; }
void GetBlockPos(int & a_BlockX, int & a_BlockY, int & a_BlockZ)
{
a_BlockX = m_Entity->GetPosX();
a_BlockY = m_Entity->GetPosY();
a_BlockZ = m_Entity->GetPosZ();
}
private:
cWindow* m_Window;
cBlockEntity *m_Entity;
cWindow * m_Window;
cBlockEntity * m_Entity;
};

View File

@ -265,7 +265,7 @@ public:
bool GetSignLines (int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4); // tolua_export
/// a_Player is using block entity at [x, y, z], handle that:
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z) {m_ChunkMap->UseBlockEntity(a_Player, a_X, a_Y, a_Z); }
void UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) {m_ChunkMap->UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ); }
void GrowTree (int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_export
void GrowTreeFromSapling(int a_BlockX, int a_BlockY, int a_BlockZ, char a_SaplingMeta); // tolua_export