1
0
Fork 0

Added beacon.

This commit is contained in:
Howaner 2014-07-30 21:59:35 +02:00
parent f095e770b8
commit 89b1bbdc5f
13 changed files with 701 additions and 45 deletions

View File

@ -3,33 +3,31 @@
#include "BeaconEntity.h"
#include "../BlockArea.h"
#include "../Entities/Player.h"
cBeaconEntity::cBeaconEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
super(E_BLOCK_BEACON, a_BlockX, a_BlockY, a_BlockZ, a_World)
cBeaconEntity::cBeaconEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World)
: super(E_BLOCK_BEACON, a_BlockX, a_BlockY, a_BlockZ, 1, 1, a_World)
, m_IsActive(false)
, m_BeaconLevel(0)
, m_PrimaryPotion(cEntityEffect::effNoEffect)
, m_SecondaryPotion(cEntityEffect::effNoEffect)
{
UpdateBeacon();
}
int cBeaconEntity::GetPyramidLevel(void)
char cBeaconEntity::CalculatePyramidLevel(void)
{
cBlockArea Area;
int MinY = GetPosY() - 4;
if (MinY < 0)
{
MinY = 0;
}
int MaxY = GetPosY() - 1;
if (MaxY < 0)
{
MaxY = 0;
}
int MinY = std::max(GetPosY() - 4, 0);
int MaxY = std::max(GetPosY() - 1, 0);
Area.Read(
m_World,
@ -42,7 +40,7 @@ int cBeaconEntity::GetPyramidLevel(void)
int Layer = 1;
int MiddleXZ = 4;
for (int Y = Area.GetSizeY() - 1; Y > 0; Y--)
for (int Y = (Area.GetSizeY() - 1); Y >= 0; Y--)
{
for (int X = MiddleXZ - Layer; X <= (MiddleXZ + Layer); X++)
{
@ -50,14 +48,122 @@ int cBeaconEntity::GetPyramidLevel(void)
{
if (!IsMineralBlock(Area.GetRelBlockType(X, Y, Z)))
{
return Layer - 1;
return (Layer - 1);
}
}
}
Layer++;
}
return Layer - 1;
return (Layer - 1);
}
bool cBeaconEntity::IsValidPotion(cEntityEffect::eType a_Potion, char a_BeaconLevel)
{
if (a_Potion == cEntityEffect::effNoEffect)
{
return true;
}
switch (a_BeaconLevel)
{
case 4:
{
// Beacon level 4
if (a_Potion == cEntityEffect::effRegeneration)
{
return true;
}
}
case 3:
{
// Beacon level 3
if (a_Potion == cEntityEffect::effStrength)
{
return true;
}
}
case 2:
{
// Beacon level 2
switch (a_Potion)
{
case cEntityEffect::effResistance:
case cEntityEffect::effJumpBoost:
{
return true;
}
}
}
case 1:
{
// Beacon level 1
switch (a_Potion)
{
case cEntityEffect::effSpeed:
case cEntityEffect::effHaste:
{
return true;
}
}
}
}
return false;
}
bool cBeaconEntity::SelectPrimaryPotion(cEntityEffect::eType a_Potion)
{
LOG("SelectPrimaryPotion!");
if (!IsValidPotion(a_Potion, m_BeaconLevel))
{
LOG("FALLSE!");
return false;
}
m_PrimaryPotion = a_Potion;
return true;
}
bool cBeaconEntity::SelectSecondaryPotion(cEntityEffect::eType a_Potion)
{
if (!IsValidPotion(a_Potion, m_BeaconLevel))
{
return false;
}
m_SecondaryPotion = a_Potion;
return true;
}
bool cBeaconEntity::IsBeaconBlocked(void)
{
bool IsBlocked = false;
for (int Y = m_PosY; Y < cChunkDef::Height; ++Y)
{
BLOCKTYPE Block = m_World->GetBlock(m_PosX, Y, m_PosZ);
if (!cBlockInfo::IsTransparent(Block))
{
IsBlocked = true;
break;
}
}
return IsBlocked;
}
@ -83,8 +189,102 @@ bool cBeaconEntity::IsMineralBlock(BLOCKTYPE a_BlockType)
void cBeaconEntity::UpdateBeacon(void)
{
if (IsBeaconBlocked())
{
m_IsActive = false;
m_BeaconLevel = 0;
}
else
{
m_BeaconLevel = CalculatePyramidLevel();
m_IsActive = (m_BeaconLevel > 0);
}
// TODO: Add achievement
}
void cBeaconEntity::GiveEffects(void)
{
if (!m_IsActive || (m_BeaconLevel < 0))
{
return;
}
int Radius = m_BeaconLevel * 10 + 10;
short EffectLevel = 0;
if ((m_BeaconLevel >= 4) && (m_PrimaryPotion == m_SecondaryPotion))
{
EffectLevel = 1;
}
cEntityEffect::eType SecondaryPotion = cEntityEffect::effNoEffect;
if ((m_BeaconLevel >= 4) && (m_PrimaryPotion != m_SecondaryPotion) && (m_SecondaryPotion > 0))
{
SecondaryPotion = m_SecondaryPotion;
}
class cPlayerCallback : public cPlayerListCallback
{
int m_Radius;
int m_PosX, m_PosY, m_PosZ;
cEntityEffect::eType m_PrimaryPotion, m_SecondaryPotion;
short m_EffectLevel;
virtual bool Item(cPlayer * a_Player)
{
Vector3d PlayerPosition = Vector3d(a_Player->GetPosition());
if (PlayerPosition.y > (double)m_PosY)
{
PlayerPosition.y = (double)m_PosY;
}
// TODO: Vanilla minecraft uses an AABB check instead of a radius one
Vector3d BeaconPosition = Vector3d(m_PosX, m_PosY, m_PosZ);
if ((PlayerPosition - BeaconPosition).Length() <= m_Radius)
{
a_Player->AddEntityEffect(m_PrimaryPotion, 180, m_EffectLevel);
if (m_SecondaryPotion != cEntityEffect::effNoEffect)
{
a_Player->AddEntityEffect(m_SecondaryPotion, 180, 0);
}
}
return false;
}
public:
cPlayerCallback(int a_Radius, int a_PosX, int a_PosY, int a_PosZ, cEntityEffect::eType a_PrimaryPotion, cEntityEffect::eType a_SecondaryPotion, short a_EffectLevel)
: m_Radius(a_Radius)
, m_PosX(a_PosX)
, m_PosY(a_PosY)
, m_PosZ(a_PosZ)
, m_PrimaryPotion(a_PrimaryPotion)
, m_SecondaryPotion(a_SecondaryPotion)
, m_EffectLevel(a_EffectLevel)
{};
} PlayerCallback(Radius, m_PosX, m_PosY, m_PosZ, m_PrimaryPotion, SecondaryPotion, EffectLevel);
GetWorld()->ForEachPlayer(PlayerCallback);
}
bool cBeaconEntity::Tick(float a_Dt, cChunk & a_Chunk)
{
// Update the beacon every 4 seconds
if ((GetWorld()->GetWorldAge() % 80) == 0)
{
UpdateBeacon();
GiveEffects();
}
return false;
}
@ -92,23 +292,94 @@ bool cBeaconEntity::Tick(float a_Dt, cChunk & a_Chunk)
void cBeaconEntity::SaveToJson(Json::Value& a_Value)
{
}
void cBeaconEntity::SendTo(cClientHandle & a_Client)
{
}
void cBeaconEntity::UsedBy(cPlayer * a_Player)
{
cWindow * Window = GetWindow();
if (Window == NULL)
{
OpenWindow(new cBeaconWindow(m_PosX, m_PosY, m_PosZ, this));
Window = GetWindow();
}
if (Window != NULL)
{
// if (a_Player->GetWindow() != Window)
// -> Because mojang doesn't send a 'close window' packet when you click the cancel button in the beacon inventory ...
{
a_Player->OpenWindow(Window);
}
}
}
bool cBeaconEntity::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++;
}
m_BeaconLevel = (char)a_Value.get("Level", 0).asInt();
int PrimaryPotion = a_Value.get("PrimaryPotion", 0).asInt();
int SecondaryPotion = a_Value.get("SecondaryPotion", 0).asInt();
if ((PrimaryPotion >= 0) && (PrimaryPotion <= (int)cEntityEffect::effSaturation))
{
m_PrimaryPotion = (cEntityEffect::eType)PrimaryPotion;
}
if ((SecondaryPotion >= 0) && (SecondaryPotion <= (int)cEntityEffect::effSaturation))
{
m_SecondaryPotion = (cEntityEffect::eType)SecondaryPotion;
}
return true;
}
void cBeaconEntity::SaveToJson(Json::Value& a_Value)
{
a_Value["x"] = m_PosX;
a_Value["y"] = m_PosY;
a_Value["z"] = m_PosZ;
Json::Value AllSlots;
int NumSlots = m_Contents.GetNumSlots();
for (int i = 0; i < NumSlots; i++)
{
Json::Value Slot;
m_Contents.GetSlot(i).GetJson(Slot);
AllSlots.append(Slot);
}
a_Value["Slots"] = AllSlots;
a_Value["Level"] = m_BeaconLevel;
a_Value["PrimaryPotion"] = (int)m_PrimaryPotion;
a_Value["SecondaryPotion"] = (int)m_SecondaryPotion;
}
void cBeaconEntity::SendTo(cClientHandle & a_Client)
{
a_Client.SendUpdateBlockEntity(*this);
}

View File

@ -1,7 +1,7 @@
#pragma once
#include "BlockEntity.h"
#include "BlockEntityWithItems.h"
@ -17,26 +17,60 @@ namespace Json
class cBeaconEntity :
public cBlockEntity
public cBlockEntityWithItems
{
typedef cBlockEntity super;
typedef cBlockEntityWithItems super;
public:
/** The initial constructor */
cBeaconEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
/** Returns the amount of layers the pyramid below the beacon has. */
int GetPyramidLevel(void);
/** Is the beacon active? */
bool IsActive(void) const { return m_IsActive; }
/** Returns the beacon level. (0 - 4) */
char GetBeaconLevel(void) const { return m_BeaconLevel; }
char GetPrimaryPotion(void) const { return m_PrimaryPotion; }
char GetSecondaryPotion(void) const { return m_SecondaryPotion; }
/** Select the primary potion. Returns false when the potion is invalid.*/
bool SelectPrimaryPotion(cEntityEffect::eType a_Potion);
/** Select the secondary potion. Returns false when the potion is invalid. */
bool SelectSecondaryPotion(cEntityEffect::eType a_Potion);
/** Calculate the amount of layers the pyramid below the beacon has. */
char CalculatePyramidLevel(void);
/** Is the beacon blocked by non-transparent blocks that are higher than the beacon? */
bool IsBeaconBlocked(void);
/** Returns true if the block is a diamond block, a golden block, an iron block or an emerald block. */
static bool IsMineralBlock(BLOCKTYPE a_BlockType);
/** Returns true if the potion can be used. */
static bool IsValidPotion(cEntityEffect::eType a_Potion, char a_BeaconLevel);
/** Update the beacon. */
void UpdateBeacon(void);
/** Give the near-players the effects. */
void GiveEffects(void);
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;
virtual bool Tick(float a_Dt, cChunk & /* a_Chunk */) override;
virtual void SaveToJson(Json::Value& a_Value) override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual bool Tick(float a_Dt, cChunk & a_Chunk) override;
virtual void UsedBy(cPlayer * a_Player) override;
protected:
bool m_IsActive;
char m_BeaconLevel;
cEntityEffect::eType m_PrimaryPotion, m_SecondaryPotion;
} ;

View File

@ -1,7 +1,7 @@
// FlowerPotEntity.cpp
// Implements the cFlowerPotEntity class representing a single sign in the world
// Implements the cFlowerPotEntity class representing a single flower pot in the world
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "json/json.h"

View File

@ -181,6 +181,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_ACACIA_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
case E_BLOCK_ACTIVATOR_RAIL: return new cBlockRailHandler (a_BlockType);
case E_BLOCK_ANVIL: return new cBlockAnvilHandler (a_BlockType);
case E_BLOCK_BEACON: return new cBlockEntityHandler (a_BlockType);
case E_BLOCK_BED: return new cBlockBedHandler (a_BlockType);
case E_BLOCK_BIG_FLOWER: return new cBlockBigFlowerHandler (a_BlockType);
case E_BLOCK_BIRCH_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);

View File

@ -94,6 +94,7 @@ private:
switch (a_BlockType)
{
case E_BLOCK_ANVIL:
case E_BLOCK_BEACON:
case E_BLOCK_BEDROCK:
case E_BLOCK_BREWING_STAND:
case E_BLOCK_CHEST:

View File

@ -1839,6 +1839,7 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
}
case E_BLOCK_OBSIDIAN:
case E_BLOCK_BEACON:
case E_BLOCK_BEDROCK:
case E_BLOCK_WATER:
case E_BLOCK_LAVA:

View File

@ -31,6 +31,7 @@
#include "Items/ItemSword.h"
#include "polarssl/md5.h"
#include "BlockEntities/BeaconEntity.h"
@ -659,6 +660,10 @@ void cClientHandle::HandlePluginMessage(const AString & a_Channel, const AString
// Client <-> Server branding exchange
SendPluginMessage("MC|Brand", "MCServer");
}
else if (a_Channel == "MC|Beacon")
{
HandleBeaconSelection(a_Message.c_str(), a_Message.size());
}
else if (a_Channel == "MC|ItemName")
{
HandleAnvilItemName(a_Message.c_str(), a_Message.size());
@ -746,6 +751,55 @@ void cClientHandle::UnregisterPluginChannels(const AStringVector & a_ChannelList
void cClientHandle::HandleBeaconSelection(const char * a_Data, size_t a_Length)
{
if (a_Length < 14)
{
SendChat("Failure setting beacon selection; bad request", mtFailure);
LOGD("Malformed MC|Beacon packet.");
return;
}
cWindow * Window = m_Player->GetWindow();
if ((Window == NULL) || (Window->GetWindowType() != cWindow::wtBeacon))
{
return;
}
cBeaconWindow * BeaconWindow = (cBeaconWindow *) Window;
if (Window->GetSlot(*m_Player, 0)->IsEmpty())
{
return;
}
cByteBuffer Buffer(a_Length);
Buffer.Write(a_Data, a_Length);
int PrimaryPotionID, SecondaryPotionID;
Buffer.ReadBEInt(PrimaryPotionID);
Buffer.ReadBEInt(SecondaryPotionID);
cEntityEffect::eType PrimaryPotion = cEntityEffect::effNoEffect;
if ((PrimaryPotionID >= 0) && (PrimaryPotionID <= (int)cEntityEffect::effSaturation))
{
PrimaryPotion = (cEntityEffect::eType)PrimaryPotionID;
}
cEntityEffect::eType SecondaryPotion = cEntityEffect::effNoEffect;
if ((SecondaryPotionID >= 0) && (SecondaryPotionID <= (int)cEntityEffect::effSaturation))
{
SecondaryPotion = (cEntityEffect::eType)SecondaryPotionID;
}
Window->SetSlot(*m_Player, 0, cItem());
BeaconWindow->GetBeaconEntity()->SelectPrimaryPotion(PrimaryPotion);
BeaconWindow->GetBeaconEntity()->SelectSecondaryPotion(SecondaryPotion);
}
void cClientHandle::HandleCommandBlockMessage(const char * a_Data, size_t a_Length)
{
if (a_Length < 14)

View File

@ -399,7 +399,10 @@ private:
/** Removes all of the channels from the list of current plugin channels. Ignores channels that are not found. */
void UnregisterPluginChannels(const AStringVector & a_ChannelList);
/** Handles the "MC|Beacon" plugin message */
void HandleBeaconSelection(const char * a_Data, size_t a_Length);
/** Handles the "MC|AdvCdm" plugin message */
void HandleCommandBlockMessage(const char * a_Data, size_t a_Length);

View File

@ -37,6 +37,7 @@ Implements the 1.7.x protocol classes:
#include "../Mobs/IncludeAllMonsters.h"
#include "../UI/Window.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
#include "../BlockEntities/MobHeadEntity.h"
#include "../BlockEntities/FlowerPotEntity.h"
@ -1328,6 +1329,7 @@ void cProtocol172::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
{
case E_BLOCK_MOB_SPAWNER: Action = 1; break; // Update mob spawner spinny mob thing
case E_BLOCK_COMMAND_BLOCK: Action = 2; break; // Update command block text
case E_BLOCK_BEACON: Action = 3; break; // Update beacon entity
case E_BLOCK_HEAD: Action = 4; break; // Update Mobhead entity
case E_BLOCK_FLOWER_POT: Action = 5; break; // Update flower pot
default: ASSERT(!"Unhandled or unimplemented BlockEntity update request!"); break;
@ -2581,6 +2583,19 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
switch (a_BlockEntity.GetBlockType())
{
case E_BLOCK_BEACON:
{
cBeaconEntity & BeaconEntity = (cBeaconEntity &)a_BlockEntity;
Writer.AddInt("x", BeaconEntity.GetPosX());
Writer.AddInt("y", BeaconEntity.GetPosY());
Writer.AddInt("z", BeaconEntity.GetPosZ());
Writer.AddInt("Primary", BeaconEntity.GetPrimaryPotion());
Writer.AddInt("Secondary", BeaconEntity.GetSecondaryPotion());
Writer.AddInt("Levels", BeaconEntity.GetBeaconLevel());
Writer.AddString("id", "Beacon"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
break;
}
case E_BLOCK_COMMAND_BLOCK:
{
cCommandBlockEntity & CommandBlockEntity = (cCommandBlockEntity &)a_BlockEntity;

View File

@ -5,6 +5,7 @@
#include "Globals.h"
#include "SlotArea.h"
#include "../Entities/Player.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/DropSpenserEntity.h"
#include "../BlockEntities/EnderChestEntity.h"
@ -1190,6 +1191,200 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player)
////////////////////////////////////////////////////////////////////////////////
// cSlotAreaBeacon:
cSlotAreaBeacon::cSlotAreaBeacon(cBeaconEntity * a_Beacon, cWindow & a_ParentWindow) :
cSlotArea(1, a_ParentWindow),
m_Beacon(a_Beacon)
{
m_Beacon->GetContents().AddListener(*this);
}
cSlotAreaBeacon::~cSlotAreaBeacon()
{
m_Beacon->GetContents().RemoveListener(*this);
}
bool cSlotAreaBeacon::IsPlaceableItem(short a_ItemType)
{
switch (a_ItemType)
{
case E_ITEM_EMERALD:
case E_ITEM_DIAMOND:
case E_ITEM_GOLD:
case E_ITEM_IRON:
{
return true;
}
}
return false;
}
void cSlotAreaBeacon::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem)
{
ASSERT((a_SlotNum >= 0) && (a_SlotNum < GetNumSlots()));
bool bAsync = false;
if (GetSlot(a_SlotNum, a_Player) == NULL)
{
LOGWARNING("GetSlot(%d) returned NULL! Ignoring click", a_SlotNum);
return;
}
switch (a_ClickAction)
{
case caShiftLeftClick:
case caShiftRightClick:
{
ShiftClicked(a_Player, a_SlotNum, a_ClickedItem);
return;
}
case caMiddleClick:
{
MiddleClicked(a_Player, a_SlotNum);
return;
}
case caDropKey:
case caCtrlDropKey:
{
DropClicked(a_Player, a_SlotNum, false);
return;
}
case caNumber1:
case caNumber2:
case caNumber3:
case caNumber4:
case caNumber5:
case caNumber6:
case caNumber7:
case caNumber8:
case caNumber9:
{
NumberClicked(a_Player, a_SlotNum, a_ClickAction);
return;
}
default:
{
break;
}
}
cItem Slot(*GetSlot(a_SlotNum, a_Player));
if (!Slot.IsSameType(a_ClickedItem))
{
LOGWARNING("*** Window lost sync at item %d in SlotArea with %d items ***", a_SlotNum, m_NumSlots);
LOGWARNING("My item: %s", ItemToFullString(Slot).c_str());
LOGWARNING("Their item: %s", ItemToFullString(a_ClickedItem).c_str());
bAsync = true;
}
cItem & DraggingItem = a_Player.GetDraggingItem();
if (DraggingItem.IsEmpty())
{
DraggingItem = Slot;
Slot.Empty();
}
else if (Slot.IsEmpty())
{
if (!IsPlaceableItem(DraggingItem.m_ItemType))
{
return;
}
Slot = DraggingItem.CopyOne();
DraggingItem.m_ItemCount -= 1;
if (DraggingItem.m_ItemCount <= 0)
{
DraggingItem.Empty();
}
}
else if (DraggingItem.m_ItemCount == 1)
{
if (!IsPlaceableItem(DraggingItem.m_ItemCount))
{
return;
}
// Switch contents
cItem tmp(DraggingItem);
DraggingItem = Slot;
Slot = tmp;
}
SetSlot(a_SlotNum, a_Player, Slot);
if (bAsync)
{
m_ParentWindow.BroadcastWholeWindow();
}
}
void cSlotAreaBeacon::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots)
{
const cItem * Slot = GetSlot(0, a_Player);
if (!Slot->IsEmpty() || !IsPlaceableItem(a_ItemStack.m_ItemType) || (a_ItemStack.m_ItemCount != 1))
{
return;
}
if (a_ShouldApply)
{
SetSlot(0, a_Player, a_ItemStack.CopyOne());
}
a_ItemStack.Empty();
}
const cItem * cSlotAreaBeacon::GetSlot(int a_SlotNum, cPlayer & a_Player) const
{
UNUSED(a_Player);
return &(m_Beacon->GetSlot(a_SlotNum));
}
void cSlotAreaBeacon::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item)
{
UNUSED(a_Player);
m_Beacon->SetSlot(a_SlotNum, a_Item);
}
void cSlotAreaBeacon::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
{
UNUSED(a_SlotNum);
// Something has changed in the window, broadcast the entire window to all clients
ASSERT(a_ItemGrid == &(m_Beacon->GetContents()));
m_ParentWindow.BroadcastWholeWindow();
}
////////////////////////////////////////////////////////////////////////////////
// cSlotAreaEnchanting:

View File

@ -15,6 +15,7 @@
class cWindow;
class cPlayer;
class cBeaconEntity;
class cChestEntity;
class cDropSpenserEntity;
class cEnderChestEntity;
@ -314,6 +315,34 @@ protected:
class cSlotAreaBeacon :
public cSlotArea,
public cItemGrid::cListener
{
typedef cSlotArea super;
public:
cSlotAreaBeacon(cBeaconEntity * a_Beacon, cWindow & a_ParentWindow);
virtual ~cSlotAreaBeacon();
bool IsPlaceableItem(short a_ItemType);
virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override;
virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots) override;
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:
cBeaconEntity * m_Beacon;
// cItemGrid::cListener overrides:
virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override;
} ;
class cSlotAreaEnchanting :
public cSlotAreaTemporary
{

View File

@ -9,6 +9,7 @@
#include "../Entities/Pickup.h"
#include "../Inventory.h"
#include "../Items/ItemHandler.h"
#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/DropSpenserEntity.h"
#include "../BlockEntities/EnderChestEntity.h"
@ -840,6 +841,36 @@ void cAnvilWindow::GetBlockPos(int & a_PosX, int & a_PosY, int & a_PosZ)
////////////////////////////////////////////////////////////////////////////////
// cBeaconWindow:
cBeaconWindow::cBeaconWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconEntity * a_Beacon) :
cWindow(wtBeacon, "Beacon"),
m_Beacon(a_Beacon)
{
m_ShouldDistributeToHotbarFirst = true;
m_SlotAreas.push_back(new cSlotAreaBeacon(m_Beacon, *this));
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
}
void cBeaconWindow::OpenedByPlayer(cPlayer & a_Player)
{
super::OpenedByPlayer(a_Player);
a_Player.GetClientHandle()->SendWindowProperty(*this, 0, m_Beacon->GetBeaconLevel());
a_Player.GetClientHandle()->SendWindowProperty(*this, 1, m_Beacon->GetPrimaryPotion());
a_Player.GetClientHandle()->SendWindowProperty(*this, 2, m_Beacon->GetSecondaryPotion());
}
////////////////////////////////////////////////////////////////////////////////
// cEnchantingWindow:

View File

@ -23,6 +23,7 @@ class cDropSpenserEntity;
class cEnderChestEntity;
class cFurnaceEntity;
class cHopperEntity;
class cBeaconEntity;
class cSlotArea;
class cSlotAreaAnvil;
class cWorld;
@ -258,6 +259,26 @@ protected:
class cBeaconWindow :
public cWindow
{
typedef cWindow super;
public:
cBeaconWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconEntity * a_Beacon);
cBeaconEntity * GetBeaconEntity(void) const { return m_Beacon; }
// cWindow Overrides:
virtual void OpenedByPlayer(cPlayer & a_Player) override;
protected:
cBeaconEntity * m_Beacon;
} ;
class cEnchantingWindow :
public cWindow
{