diff options
Diffstat (limited to 'source/BlockEntities')
21 files changed, 0 insertions, 3038 deletions
diff --git a/source/BlockEntities/BlockEntity.cpp b/source/BlockEntities/BlockEntity.cpp deleted file mode 100644 index 41a488717..000000000 --- a/source/BlockEntities/BlockEntity.cpp +++ /dev/null @@ -1,44 +0,0 @@ - -// BlockEntity.cpp - -// Implements the cBlockEntity class that is the common ancestor for all block entities - -#include "Globals.h" -#include "BlockEntity.h" -#include "ChestEntity.h" -#include "DispenserEntity.h" -#include "DropperEntity.h" -#include "FurnaceEntity.h" -#include "HopperEntity.h" -#include "JukeboxEntity.h" -#include "NoteEntity.h" -#include "SignEntity.h" - - - - - -cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) -{ - 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); - } - LOGD("%s: Requesting creation of an unknown block entity - block type %d (%s)", - __FUNCTION__, a_BlockType, ItemTypeToString(a_BlockType).c_str() - ); - return NULL; -} - - - - diff --git a/source/BlockEntities/BlockEntity.h b/source/BlockEntities/BlockEntity.h deleted file mode 100644 index 0d358b556..000000000 --- a/source/BlockEntities/BlockEntity.h +++ /dev/null @@ -1,106 +0,0 @@ - -#pragma once - -#include "../ClientHandle.h" -#include "../World.h" - - - - - -namespace Json -{ - class Value; -}; - -class cPlayer; -class cPacket; - - - - - -// tolua_begin -class cBlockEntity -{ -protected: - cBlockEntity(BLOCKTYPE a_BlockType, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) : - m_PosX(a_BlockX), - m_PosY(a_BlockY), - m_PosZ(a_BlockZ), - m_RelX(a_BlockX - cChunkDef::Width * FAST_FLOOR_DIV(a_BlockX, cChunkDef::Width)), - m_RelZ(a_BlockZ - cChunkDef::Width * FAST_FLOOR_DIV(a_BlockZ, cChunkDef::Width)), - m_BlockType(a_BlockType), - m_World(a_World) - { - } - -public: - // tolua_end - - virtual ~cBlockEntity() {}; // force a virtual destructor in all descendants - - virtual void Destroy(void) {}; - - void SetWorld(cWorld * a_World) - { - m_World = a_World; - } - - /// Creates a new block entity for the specified block type - /// If a_World is valid, then the entity is created bound to that world - /// Returns NULL for unknown block types - static cBlockEntity * CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World = NULL); - - static const char * GetClassStatic(void) // Needed for ManualBindings's ForEach templates - { - return "cBlockEntity"; - } - - // tolua_begin - - // Position, in absolute block coordinates: - int GetPosX(void) const { return m_PosX; } - int GetPosY(void) const { return m_PosY; } - int GetPosZ(void) const { return m_PosZ; } - - BLOCKTYPE GetBlockType(void) const { return m_BlockType; } - - cWorld * GetWorld(void) const {return m_World; } - - int GetChunkX(void) const { return FAST_FLOOR_DIV(m_PosX, cChunkDef::Width); } - int GetChunkZ(void) const { return FAST_FLOOR_DIV(m_PosZ, cChunkDef::Width); } - - int GetRelX(void) const { return m_RelX; } - int GetRelZ(void) const { return m_RelZ; } - - // tolua_end - - virtual void SaveToJson (Json::Value & a_Value) = 0; - - /// Called when a player uses this entity; should open the UI window - virtual void UsedBy( cPlayer * a_Player ) = 0; - - /** Sends the packet defining the block entity to the client specified. - To send to all eligible clients, use cWorld::BroadcastBlockEntity() - */ - virtual void SendTo(cClientHandle & a_Client) = 0; - - /// Ticks the entity; returns true if the chunk should be marked as dirty as a result of this ticking. By default does nothing. - virtual bool Tick(float a_Dt, cChunk & a_Chunk) { return false; } - -protected: - /// Position in absolute block coordinates - int m_PosX, m_PosY, m_PosZ; - - /// Position relative to the chunk, used to speed up ticking - int m_RelX, m_RelZ; - - BLOCKTYPE m_BlockType; - - cWorld * m_World; -} ; // tolua_export - - - - diff --git a/source/BlockEntities/BlockEntityWithItems.h b/source/BlockEntities/BlockEntityWithItems.h deleted file mode 100644 index 0846ae17e..000000000 --- a/source/BlockEntities/BlockEntityWithItems.h +++ /dev/null @@ -1,86 +0,0 @@ - -// BlockEntityWithItems.h - -// Declares the cBlockEntityWithItems class representing a common ancestor for all block entities that have an ItemGrid - - - - - -#pragma once - -#include "BlockEntity.h" -#include "../ItemGrid.h" - - - - - -// tolua_begin -class cBlockEntityWithItems : - public cBlockEntity - // tolua_end - // tolua doesn't seem to support multiple inheritance? - , public cItemGrid::cListener - // tolua_begin -{ - typedef cBlockEntity super; - -public: - // tolua_end - - cBlockEntityWithItems( - BLOCKTYPE a_BlockType, // Type of the block that the entity represents - int a_BlockX, int a_BlockY, int a_BlockZ, // Position of the block entity - int a_ItemGridWidth, int a_ItemGridHeight, // Dimensions of the ItemGrid - cWorld * a_World // Optional world to assign to the entity - ) : - super(a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World), - m_Contents(a_ItemGridWidth, a_ItemGridHeight) - { - m_Contents.AddListener(*this); - } - - virtual void Destroy(void) override - { - // Drop the contents as pickups: - ASSERT(m_World != NULL); - cItems Pickups; - m_Contents.CopyToItems(Pickups); - m_Contents.Clear(); - m_World->SpawnItemPickups(Pickups, m_PosX, m_PosY, m_PosZ); - } - - // tolua_begin - - const cItem & GetSlot(int a_SlotNum) const { return m_Contents.GetSlot(a_SlotNum); } - const cItem & GetSlot(int a_X, int a_Y) const { return m_Contents.GetSlot(a_X, a_Y); } - - void SetSlot(int a_SlotNum, const cItem & a_Item) { m_Contents.SetSlot(a_SlotNum, a_Item); } - void SetSlot(int a_X, int a_Y, const cItem & a_Item) { m_Contents.SetSlot(a_X, a_Y, a_Item); } - - /// Returns the ItemGrid used for storing the contents - cItemGrid & GetContents(void) { return m_Contents; } - - // tolua_end - - /// Const version of the GetContents() function for C++ type-safety - const cItemGrid & GetContents(void) const { return m_Contents; } - -protected: - cItemGrid m_Contents; - - // cItemGrid::cListener overrides: - virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum) - { - ASSERT(a_Grid == &m_Contents); - if (m_World != NULL) - { - m_World->MarkChunkDirty(GetChunkX(), GetChunkZ()); - } - } -} ; // tolua_export - - - - diff --git a/source/BlockEntities/ChestEntity.cpp b/source/BlockEntities/ChestEntity.cpp deleted file mode 100644 index ca2626bc9..000000000 --- a/source/BlockEntities/ChestEntity.cpp +++ /dev/null @@ -1,172 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "ChestEntity.h" -#include "../Item.h" -#include "../Entities/Player.h" -#include "../UI/Window.h" -#include <json/json.h> - - - - - -cChestEntity::cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) : - super(E_BLOCK_CHEST, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World) -{ - cBlockEntityWindowOwner::SetBlockEntity(this); -} - - - - - -cChestEntity::~cChestEntity() -{ - cWindow * Window = GetWindow(); - if (Window != NULL) - { - Window->OwnerDestroyed(); - } -} - - - - - -bool cChestEntity::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 cChestEntity::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 cChestEntity::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 cChestEntity::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 cChestEntity::OpenNewWindow(void) -{ - // Callback for opening together with neighbor chest: - class cOpenDouble : - public cChestCallback - { - cChestEntity * m_ThisChest; - public: - cOpenDouble(cChestEntity * a_ThisChest) : - m_ThisChest(a_ThisChest) - { - } - - virtual bool Item(cChestEntity * a_Chest) override - { - // The primary chest should eb the one with lesser X or Z coord: - cChestEntity * Primary = a_Chest; - cChestEntity * Secondary = m_ThisChest; - if ( - (Primary->GetPosX() > Secondary->GetPosX()) || - (Primary->GetPosZ() > Secondary->GetPosZ()) - ) - { - std::swap(Primary, Secondary); - } - m_ThisChest->OpenWindow(new cChestWindow(Primary, Secondary)); - return false; - } - } ; - - // Scan neighbors for adjacent chests: - cOpenDouble OpenDbl(this); - if ( - m_World->DoWithChestAt(m_PosX - 1, m_PosY, m_PosZ, OpenDbl) || - m_World->DoWithChestAt(m_PosX + 1, m_PosY, m_PosZ, OpenDbl) || - m_World->DoWithChestAt(m_PosX , m_PosY, m_PosZ - 1, OpenDbl) || - m_World->DoWithChestAt(m_PosX , m_PosY, m_PosZ + 1, OpenDbl) - ) - { - // The double-chest window has been opened in the callback - return; - } - - // There is no chest neighbor, open a single-chest window: - OpenWindow(new cChestWindow(this)); -} - - - - diff --git a/source/BlockEntities/ChestEntity.h b/source/BlockEntities/ChestEntity.h deleted file mode 100644 index 4f2c21e91..000000000 --- a/source/BlockEntities/ChestEntity.h +++ /dev/null @@ -1,59 +0,0 @@ - -#pragma once - -#include "BlockEntityWithItems.h" -#include "../UI/WindowOwner.h" - - - - - -namespace Json -{ - class Value; -}; - -class cClientHandle; -class cServer; -class cNBTData; - - - - - -class cChestEntity : // tolua_export - public cBlockEntityWindowOwner, - // tolua_begin - public cBlockEntityWithItems -{ - typedef cBlockEntityWithItems super; - -public: - enum { - ContentsHeight = 3, - ContentsWidth = 9, - } ; - - // tolua_end - - /// Constructor used for normal operation - cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World); - - virtual ~cChestEntity(); - - static const char * GetClassStatic(void) { return "cChestEntity"; } - - 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 - - - - diff --git a/source/BlockEntities/DispenserEntity.cpp b/source/BlockEntities/DispenserEntity.cpp deleted file mode 100644 index 374f3d6e3..000000000 --- a/source/BlockEntities/DispenserEntity.cpp +++ /dev/null @@ -1,215 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "DispenserEntity.h" -#include "../Entities/Player.h" -#include "../Simulator/FluidSimulator.h" -#include "../Chunk.h" - - - - - -cDispenserEntity::cDispenserEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) : - super(E_BLOCK_DISPENSER, a_BlockX, a_BlockY, a_BlockZ, a_World) -{ - SetBlockEntity(this); // cBlockEntityWindowOwner -} - - - - - -void cDispenserEntity::DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum) -{ - int DispX = m_RelX; - int DispY = m_PosY; - int DispZ = m_RelZ; - NIBBLETYPE Meta = a_Chunk.GetMeta(m_RelX, m_PosY, m_RelZ); - AddDropSpenserDir(DispX, DispY, DispZ, Meta); - cChunk * DispChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(DispX, DispZ); - if (DispChunk == NULL) - { - // Would dispense into / interact with a non-loaded chunk, ignore the tick - return; - } - BLOCKTYPE DispBlock = DispChunk->GetBlock(DispX, DispY, DispZ); - - // Dispense the item: - switch (m_Contents.GetSlot(a_SlotNum).m_ItemType) - { - case E_ITEM_BUCKET: - { - LOGD("Dispensing empty bucket in slot %d; DispBlock is \"%s\" (%d).", a_SlotNum, ItemTypeToString(DispBlock).c_str(), DispBlock); - switch (DispBlock) - { - case E_BLOCK_STATIONARY_WATER: - case E_BLOCK_WATER: - { - if (ScoopUpLiquid(a_SlotNum, E_ITEM_WATER_BUCKET)) - { - DispChunk->SetBlock(DispX, DispY, DispZ, E_BLOCK_AIR, 0); - } - break; - } - case E_BLOCK_STATIONARY_LAVA: - case E_BLOCK_LAVA: - { - if (ScoopUpLiquid(a_SlotNum, E_ITEM_LAVA_BUCKET)) - { - DispChunk->SetBlock(DispX, DispY, DispZ, E_BLOCK_AIR, 0); - } - break; - } - default: - { - DropFromSlot(a_Chunk, a_SlotNum); - break; - } - } - break; - } // E_ITEM_BUCKET - - case E_ITEM_WATER_BUCKET: - { - LOGD("Dispensing water bucket in slot %d; DispBlock is \"%s\" (%d).", a_SlotNum, ItemTypeToString(DispBlock).c_str(), DispBlock); - if (EmptyLiquidBucket(DispBlock, a_SlotNum)) - { - DispChunk->SetBlock(DispX, DispY, DispZ, E_BLOCK_WATER, 0); - } - else - { - DropFromSlot(a_Chunk, a_SlotNum); - } - break; - } - - case E_ITEM_LAVA_BUCKET: - { - LOGD("Dispensing lava bucket in slot %d; DispBlock is \"%s\" (%d).", a_SlotNum, ItemTypeToString(DispBlock).c_str(), DispBlock); - if (EmptyLiquidBucket(DispBlock, a_SlotNum)) - { - DispChunk->SetBlock(DispX, DispY, DispZ, E_BLOCK_LAVA, 0); - } - else - { - DropFromSlot(a_Chunk, a_SlotNum); - } - break; - } - - case E_ITEM_SPAWN_EGG: - { - double MobX = 0.5 + (DispX + DispChunk->GetPosX() * cChunkDef::Width); - double MobZ = 0.5 + (DispZ + DispChunk->GetPosZ() * cChunkDef::Width); - if (m_World->SpawnMob(MobX, DispY, MobZ, (cMonster::eType)m_Contents.GetSlot(a_SlotNum).m_ItemDamage) >= 0) - { - m_Contents.ChangeSlotCount(a_SlotNum, -1); - } - break; - } - - case E_BLOCK_TNT: - { - // Spawn a primed TNT entity, if space allows: - if (DispChunk->GetBlock(DispX, DispY, DispZ) == E_BLOCK_AIR) - { - double TNTX = 0.5 + (DispX + DispChunk->GetPosX() * cChunkDef::Width); - double TNTZ = 0.5 + (DispZ + DispChunk->GetPosZ() * cChunkDef::Width); - m_World->SpawnPrimedTNT(TNTX, DispY + 0.5, TNTZ, 4, 0); // 4 seconds fuse, no initial velocity - m_Contents.ChangeSlotCount(a_SlotNum, -1); - } - break; - } - - case E_ITEM_FLINT_AND_STEEL: - { - // Spawn fire if the block in front is air. - if (DispChunk->GetBlock(DispX, DispY, DispZ) == E_BLOCK_AIR) - { - DispChunk->SetBlock(DispX, DispY, DispZ, E_BLOCK_FIRE, 0); - m_Contents.SetSlot(a_SlotNum, m_Contents.GetSlot(a_SlotNum).m_ItemType, m_Contents.GetSlot(a_SlotNum).m_ItemCount, m_Contents.GetSlot(a_SlotNum).m_ItemDamage + 1); - // If the durability has run out destroy the item. - if (m_Contents.GetSlot(a_SlotNum).m_ItemDamage > 64) - { - m_Contents.ChangeSlotCount(a_SlotNum, -1); - } - } - break; - } - - default: - { - DropFromSlot(a_Chunk, a_SlotNum); - break; - } - } // switch (ItemType) -} - - - - - - -bool cDispenserEntity::ScoopUpLiquid(int a_SlotNum, short a_BucketItemType) -{ - cItem LiquidBucket(a_BucketItemType, 1); - if (m_Contents.GetSlot(a_SlotNum).m_ItemCount == 1) - { - // Special case: replacing one empty bucket with one full bucket - m_Contents.SetSlot(a_SlotNum, LiquidBucket); - return true; - } - - // There are stacked buckets at the selected slot, see if a full bucket will fit somewhere else - if (m_Contents.HowManyCanFit(LiquidBucket) < 1) - { - // Cannot fit into m_Contents - return false; - } - - m_Contents.ChangeSlotCount(a_SlotNum, -1); - m_Contents.AddItem(LiquidBucket); - return true; -} - - - - - -bool cDispenserEntity::EmptyLiquidBucket(BLOCKTYPE a_BlockInFront, int a_SlotNum) -{ - if ( - (a_BlockInFront != E_BLOCK_AIR) && - !IsBlockLiquid(a_BlockInFront) && - !cFluidSimulator::CanWashAway(a_BlockInFront) - ) - { - // Not a suitable block in front - return false; - } - - cItem EmptyBucket(E_ITEM_BUCKET, 1); - if (m_Contents.GetSlot(a_SlotNum).m_ItemCount == 1) - { - // Change the single full bucket present into a single empty bucket - m_Contents.SetSlot(a_SlotNum, EmptyBucket); - return true; - } - - // There are full buckets stacked at this slot, check if we can fit in the empty bucket - if (m_Contents.HowManyCanFit(EmptyBucket) < 1) - { - // The empty bucket wouldn't fit into m_Contents - return false; - } - - // The empty bucket fits in, remove one full bucket and add the empty one - m_Contents.ChangeSlotCount(a_SlotNum, -1); - m_Contents.AddItem(EmptyBucket); - return true; -} - - - - diff --git a/source/BlockEntities/DispenserEntity.h b/source/BlockEntities/DispenserEntity.h deleted file mode 100644 index fdfe4e5b4..000000000 --- a/source/BlockEntities/DispenserEntity.h +++ /dev/null @@ -1,38 +0,0 @@ - -#pragma once - -#include "DropSpenserEntity.h" - - - - - -// tolua_begin -class cDispenserEntity : - public cDropSpenserEntity -{ - typedef cDropSpenserEntity super; - -public: - - // tolua_end - - /// Constructor used for normal operation - cDispenserEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World); - - static const char * GetClassStatic(void) { return "cDispenserEntity"; } - -private: - // cDropSpenser overrides: - virtual void DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum) override; - - /// If such a bucket can fit, adds it to m_Contents and returns true - bool ScoopUpLiquid(int a_SlotNum, short a_BucketItemType); - - /// If the a_BlockInFront is liquidable and the empty bucket can fit, does the m_Contents processing and returns true - bool EmptyLiquidBucket(BLOCKTYPE a_BlockInFront, int a_SlotNum); -} ; // tolua_export - - - - diff --git a/source/BlockEntities/DropSpenserEntity.cpp b/source/BlockEntities/DropSpenserEntity.cpp deleted file mode 100644 index 823ed598f..000000000 --- a/source/BlockEntities/DropSpenserEntity.cpp +++ /dev/null @@ -1,266 +0,0 @@ - -// DropSpenserEntity.cpp - -// Declares the cDropSpenserEntity class representing a common ancestor to the cDispenserEntity and cDropperEntity -// The dropper and dispenser only needs to override the DropSpenseFromSlot() function to provide the specific item behavior - -#include "Globals.h" -#include "DropSpenserEntity.h" -#include "../Entities/Player.h" -#include "../Chunk.h" - - - - - -cDropSpenserEntity::cDropSpenserEntity(BLOCKTYPE a_BlockType, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) : - super(a_BlockType, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World), - m_ShouldDropSpense(false), - m_IsPowered(false) -{ - SetBlockEntity(this); // cBlockEntityWindowOwner -} - - - - - -cDropSpenserEntity::~cDropSpenserEntity() -{ - // Tell window its owner is destroyed - cWindow * Window = GetWindow(); - if (Window != NULL) - { - Window->OwnerDestroyed(); - } -} - - - - - -void cDropSpenserEntity::AddDropSpenserDir(int & a_BlockX, int & a_BlockY, int & a_BlockZ, NIBBLETYPE a_Direction) -{ - switch (a_Direction) - { - case E_META_DROPSPENSER_FACING_YM: a_BlockY--; return; - case E_META_DROPSPENSER_FACING_YP: a_BlockY++; return; - case E_META_DROPSPENSER_FACING_ZM: a_BlockZ--; return; - case E_META_DROPSPENSER_FACING_ZP: a_BlockZ++; return; - case E_META_DROPSPENSER_FACING_XM: a_BlockX--; return; - case E_META_DROPSPENSER_FACING_XP: a_BlockX++; return; - } - LOGWARNING("%s: Unhandled direction: %d", __FUNCTION__, a_Direction); - return; -} - - - - - -void cDropSpenserEntity::DropSpense(cChunk & a_Chunk) -{ - // Pick one of the occupied slots: - int OccupiedSlots[9]; - int SlotsCnt = 0; - for (int i = m_Contents.GetNumSlots() - 1; i >= 0; i--) - { - if (!m_Contents.GetSlot(i).IsEmpty()) - { - OccupiedSlots[SlotsCnt] = i; - SlotsCnt++; - } - } // for i - m_Contents[] - - if (SlotsCnt == 0) - { - // Nothing in the dropspenser, play the click sound - m_World->BroadcastSoundEffect("random.click", m_PosX * 8, m_PosY * 8, m_PosZ * 8, 1.0f, 1.2f); - return; - } - - int RandomSlot = m_World->GetTickRandomNumber(SlotsCnt - 1); - - // DropSpense the item, using the specialized behavior in the subclasses: - DropSpenseFromSlot(a_Chunk, OccupiedSlots[RandomSlot]); - - // Broadcast a smoke and click effects: - NIBBLETYPE Meta = a_Chunk.GetMeta(m_RelX, m_PosY, m_RelZ); - int SmokeDir = 0; - switch (Meta) - { - case E_META_DROPSPENSER_FACING_YP: SmokeDir = 4; break; // YP & YM don't have associated smoke dirs, just do 4 (centre of block) - case E_META_DROPSPENSER_FACING_YM: SmokeDir = 4; break; - case E_META_DROPSPENSER_FACING_XM: SmokeDir = 3; break; - case E_META_DROPSPENSER_FACING_XP: SmokeDir = 5; break; - case E_META_DROPSPENSER_FACING_ZM: SmokeDir = 1; break; - case E_META_DROPSPENSER_FACING_ZP: SmokeDir = 7; break; - } - m_World->BroadcastSoundParticleEffect(2000, m_PosX, m_PosY, m_PosZ, SmokeDir); - m_World->BroadcastSoundEffect("random.click", m_PosX * 8, m_PosY * 8, m_PosZ * 8, 1.0f, 1.0f); - - // Update the UI window, if open: - cWindow * Window = GetWindow(); - if (Window != NULL) - { - Window->BroadcastWholeWindow(); - } -} - - - - - -void cDropSpenserEntity::Activate(void) -{ - m_ShouldDropSpense = true; -} - - - - - -void cDropSpenserEntity::SetRedstonePower(bool a_IsPowered) -{ - if (a_IsPowered && !m_IsPowered) - { - Activate(); - } - m_IsPowered = a_IsPowered; -} - - - - - -bool cDropSpenserEntity::Tick(float a_Dt, cChunk & a_Chunk) -{ - if (!m_ShouldDropSpense) - { - return false; - } - - m_ShouldDropSpense = false; - DropSpense(a_Chunk); - return true; -} - - - - - -bool cDropSpenserEntity::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 Contents; - Contents.FromJson(*itr); - m_Contents.SetSlot(SlotIdx, Contents); - SlotIdx++; - if (SlotIdx >= m_Contents.GetNumSlots()) - { - return true; - } - } - - return true; -} - - - - - -void cDropSpenserEntity::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; -} - - - - - -void cDropSpenserEntity::SendTo(cClientHandle & a_Client) -{ - // Nothing needs to be sent - UNUSED(a_Client); -} - - - - - -void cDropSpenserEntity::UsedBy(cPlayer * a_Player) -{ - cWindow * Window = GetWindow(); - if (Window == NULL) - { - OpenWindow(new cDropSpenserWindow(m_PosX, m_PosY, m_PosZ, this)); - Window = GetWindow(); - } - - if (Window != NULL) - { - if (a_Player->GetWindow() != Window) - { - a_Player->OpenWindow(Window); - } - } -} - - - - - -void cDropSpenserEntity::DropFromSlot(cChunk & a_Chunk, int a_SlotNum) -{ - int DispX = m_PosX; - int DispY = m_PosY; - int DispZ = m_PosZ; - NIBBLETYPE Meta = a_Chunk.GetMeta(m_RelX, m_PosY, m_RelZ); - AddDropSpenserDir(DispX, DispY, DispZ, Meta); - - cItems Pickups; - Pickups.push_back(m_Contents.RemoveOneItem(a_SlotNum)); - - const int PickupSpeed = m_World->GetTickRandomNumber(4) + 2; // At least 2, at most 6 - int PickupSpeedX = 0, PickupSpeedY = 0, PickupSpeedZ = 0; - switch (Meta) - { - case E_META_DROPSPENSER_FACING_YP: PickupSpeedY = PickupSpeed; break; - case E_META_DROPSPENSER_FACING_YM: PickupSpeedY = -PickupSpeed; break; - case E_META_DROPSPENSER_FACING_XM: PickupSpeedX = -PickupSpeed; break; - case E_META_DROPSPENSER_FACING_XP: PickupSpeedX = PickupSpeed; break; - case E_META_DROPSPENSER_FACING_ZM: PickupSpeedZ = -PickupSpeed; break; - case E_META_DROPSPENSER_FACING_ZP: PickupSpeedZ = PickupSpeed; break; - } - - double MicroX, MicroY, MicroZ; - MicroX = DispX + 0.5; - MicroY = DispY + 0.4; // Slightly less than half, to accomodate actual texture hole on DropSpenser - MicroZ = DispZ + 0.5; - - - m_World->SpawnItemPickups(Pickups, MicroX, MicroY, MicroZ, PickupSpeedX, PickupSpeedY, PickupSpeedZ); -} - - - - diff --git a/source/BlockEntities/DropSpenserEntity.h b/source/BlockEntities/DropSpenserEntity.h deleted file mode 100644 index 0e9039915..000000000 --- a/source/BlockEntities/DropSpenserEntity.h +++ /dev/null @@ -1,89 +0,0 @@ - -// DropSpenser.h - -// Declares the cDropSpenser class representing a common ancestor to the cDispenserEntity and cDropperEntity -// The dropper and dispenser only needs to override the DropSpenseFromSlot() function to provide the specific item behavior - - - - - -#pragma once - -#include "BlockEntityWithItems.h" -#include "../UI/WindowOwner.h" - - - - - -namespace Json -{ - class Value; -} - -class cClientHandle; -class cServer; - - - - - -class cDropSpenserEntity : // tolua_export - public cBlockEntityWindowOwner, - // tolua_begin - public cBlockEntityWithItems -{ - typedef cBlockEntityWithItems super; - -public: - enum { - ContentsHeight = 3, - ContentsWidth = 3, - } ; - - // tolua_end - - cDropSpenserEntity(BLOCKTYPE a_BlockType, int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World); - virtual ~cDropSpenserEntity(); - - static const char * GetClassStatic(void) { return "cDropSpenserEntity"; } - - bool LoadFromJson(const Json::Value & a_Value); - - // cBlockEntity overrides: - virtual void SaveToJson(Json::Value & a_Value) override; - virtual bool Tick(float a_Dt, cChunk & a_Chunk) override; - virtual void SendTo(cClientHandle & a_Client) override; - virtual void UsedBy(cPlayer * a_Player) override; - - // tolua_begin - - /// Modifies the block coords to match the dropspenser direction given (where the dropspensed pickups should materialize) - void AddDropSpenserDir(int & a_BlockX, int & a_BlockY, int & a_BlockZ, NIBBLETYPE a_Direction); - - /// Sets the dropspenser to dropspense an item in the next tick - void Activate(void); - - /// Sets the internal redstone power flag to "on" or "off", depending on the parameter. Calls Activate() if appropriate - void SetRedstonePower(bool a_IsPowered); - - // tolua_end - -protected: - bool m_ShouldDropSpense; ///< If true, the dropspenser will dropspense an item in the next tick - bool m_IsPowered; ///< Set to true when the dropspenser receives redstone power. - - /// Does the actual work on dropspensing an item. Chooses the slot, calls DropSpenseFromSlot() and handles smoke / sound effects - void DropSpense(cChunk & a_Chunk); - - /// Override this function to provide the specific behavior for item dropspensing (drop / shoot / pour / ...) - virtual void DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum) = 0; - - /// Helper function, drops one item from the specified slot (like a dropper) - void DropFromSlot(cChunk & a_Chunk, int a_SlotNum); -} ; // tolua_export - - - - diff --git a/source/BlockEntities/DropperEntity.cpp b/source/BlockEntities/DropperEntity.cpp deleted file mode 100644 index 5d4a8ad97..000000000 --- a/source/BlockEntities/DropperEntity.cpp +++ /dev/null @@ -1,32 +0,0 @@ - -// DropperEntity.cpp - -// Implements the cRtopperEntity class representing a Dropper block entity - -#include "Globals.h" -#include "DropperEntity.h" -#include "../Entities/Player.h" -#include "../Simulator/FluidSimulator.h" - - - - - -cDropperEntity::cDropperEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) : - super(E_BLOCK_DROPPER, a_BlockX, a_BlockY, a_BlockZ, a_World) -{ - SetBlockEntity(this); // cBlockEntityWindowOwner -} - - - - - -void cDropperEntity::DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum) -{ - DropFromSlot(a_Chunk, a_SlotNum); -} - - - - diff --git a/source/BlockEntities/DropperEntity.h b/source/BlockEntities/DropperEntity.h deleted file mode 100644 index 8e07bc6f8..000000000 --- a/source/BlockEntities/DropperEntity.h +++ /dev/null @@ -1,46 +0,0 @@ - -// DropperEntity.h - -// Declares the cDropperEntity class representing a dropper block entity - - - - - -#pragma once - -#include "DropSpenserEntity.h" - - - - - -// tolua_begin -class cDropperEntity : - public cDropSpenserEntity -{ - typedef cDropSpenserEntity super; - -public: - - // tolua_end - - /// Constructor used for normal operation - cDropperEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World); - - static const char * GetClassStatic(void) { return "cDropperEntity"; } - -protected: - // cDropSpenserEntity overrides: - virtual void DropSpenseFromSlot(cChunk & a_Chunk, int a_SlotNum) override; - - /** Takes an item from slot a_SlotNum and puts it into the container in front of the dropper. - Called when there's a container directly in front of the dropper, - so the dropper should store items there, rather than dropping. - */ - void PutIntoContainer(cChunk & a_Chunk, int a_SlotNum, BLOCKTYPE a_ContainerBlock, int a_ContainerX, int a_ContainerY, int a_ContainerZ); -} ; // tolua_export - - - - diff --git a/source/BlockEntities/FurnaceEntity.cpp b/source/BlockEntities/FurnaceEntity.cpp deleted file mode 100644 index ec5ebe8b9..000000000 --- a/source/BlockEntities/FurnaceEntity.cpp +++ /dev/null @@ -1,479 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "FurnaceEntity.h" -#include "../UI/Window.h" -#include "../Entities/Player.h" -#include "../Root.h" -#include "../Chunk.h" -#include <json/json.h> - - - - - - -enum -{ - PROGRESSBAR_SMELTING = 0, - PROGRESSBAR_FUEL = 1, -} ; - - - - - -cFurnaceEntity::cFurnaceEntity(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cWorld * a_World) : - super(E_BLOCK_FURNACE, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World), - m_BlockType(a_BlockType), - m_BlockMeta(a_BlockMeta), - m_CurrentRecipe(NULL), - m_IsCooking((a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_LIT_FURNACE)), - m_NeedCookTime(0), - m_TimeCooked(0), - m_FuelBurnTime(0), - m_TimeBurned(0), - m_LastProgressFuel(0), - m_LastProgressCook(0) -{ - cBlockEntityWindowOwner::SetBlockEntity(this); - m_Contents.AddListener(*this); -} - - - - - -cFurnaceEntity::~cFurnaceEntity() -{ - // Tell window its owner is destroyed - cWindow * Window = GetWindow(); - if (Window != NULL) - { - Window->OwnerDestroyed(); - } -} - - - - - -void cFurnaceEntity::UsedBy(cPlayer * a_Player) -{ - if (GetWindow() == NULL) - { - OpenWindow(new cFurnaceWindow(m_PosX, m_PosY, m_PosZ, this)); - } - cWindow * Window = GetWindow(); - if (Window != NULL) - { - if (a_Player->GetWindow() != Window) - { - a_Player->OpenWindow(Window); - BroadcastProgress(PROGRESSBAR_FUEL, m_LastProgressFuel); - BroadcastProgress(PROGRESSBAR_SMELTING, m_LastProgressCook); - } - } -} - - - - - -/// Restarts cooking. Used after the furnace is loaded from storage to set up the internal variables so that cooking continues, if it was active. Returns true if cooking. -bool cFurnaceEntity::ContinueCooking(void) -{ - UpdateInput(); - UpdateFuel(); - return m_IsCooking; -} - - - - - -bool cFurnaceEntity::Tick(float a_Dt, cChunk & a_Chunk) -{ - if (m_FuelBurnTime <= 0) - { - // No fuel is burning, reset progressbars and bail out - if ((m_LastProgressCook > 0) || (m_LastProgressFuel > 0)) - { - UpdateProgressBars(); - } - return false; - } - - if (m_IsCooking) - { - m_TimeCooked++; - if (m_TimeCooked >= m_NeedCookTime) - { - // Finished smelting one item - FinishOne(a_Chunk); - } - } - - m_TimeBurned++; - if (m_TimeBurned >= m_FuelBurnTime) - { - // The current fuel has been exhausted, use another one, if possible - BurnNewFuel(); - } - - UpdateProgressBars(); - - return true; -} - - - - - -bool cFurnaceEntity::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_NeedCookTime = (int)(a_Value.get("CookTime", 0).asDouble() / 50); - m_TimeCooked = (int)(a_Value.get("TimeCooked", 0).asDouble() / 50); - m_FuelBurnTime = (int)(a_Value.get("BurnTime", 0).asDouble() / 50); - m_TimeBurned = (int)(a_Value.get("TimeBurned", 0).asDouble() / 50); - - return true; -} - - - - - -void cFurnaceEntity::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["CookTime"] = m_NeedCookTime * 50; - a_Value["TimeCooked"] = m_TimeCooked * 50; - a_Value["BurnTime"] = m_FuelBurnTime * 50; - a_Value["TimeBurned"] = m_TimeBurned * 50; -} - - - - - -void cFurnaceEntity::SendTo(cClientHandle & a_Client) -{ - // Nothing needs to be sent - UNUSED(a_Client); -} - - - - - -void cFurnaceEntity::BroadcastProgress(int a_ProgressbarID, short a_Value) -{ - cWindow * Window = GetWindow(); - if (Window != NULL) - { - Window->BroadcastProgress(a_ProgressbarID, a_Value); - } -} - - - - - -/// One item finished cooking -void cFurnaceEntity::FinishOne(cChunk & a_Chunk) -{ - m_TimeCooked = 0; - - if (m_Contents.GetSlot(fsOutput).IsEmpty()) - { - m_Contents.SetSlot(fsOutput, *m_CurrentRecipe->Out); - } - else - { - m_Contents.ChangeSlotCount(fsOutput, m_CurrentRecipe->Out->m_ItemCount); - } - m_Contents.ChangeSlotCount(fsInput, -m_CurrentRecipe->In->m_ItemCount); - - UpdateIsCooking(); -} - - - - - -void cFurnaceEntity::BurnNewFuel(void) -{ - cFurnaceRecipe * FR = cRoot::Get()->GetFurnaceRecipe(); - int NewTime = FR->GetBurnTime(m_Contents.GetSlot(fsFuel)); - if (NewTime == 0) - { - // The item in the fuel slot is not suitable - m_FuelBurnTime = 0; - m_TimeBurned = 0; - SetIsCooking(false); - return; - } - - // Is the input and output ready for cooking? - if (!CanCookInputToOutput()) - { - return; - } - - // Burn one new fuel: - m_FuelBurnTime = NewTime; - m_TimeBurned = 0; - SetIsCooking(true); - if (m_Contents.GetSlot(fsFuel).m_ItemType == E_ITEM_LAVA_BUCKET) - { - m_Contents.SetSlot(fsFuel, cItem(E_ITEM_BUCKET)); - } - else - { - m_Contents.ChangeSlotCount(fsFuel, -1); - } -} - - - - - -void cFurnaceEntity::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) -{ - super::OnSlotChanged(a_ItemGrid, a_SlotNum); - - if (m_World == NULL) - { - // The furnace isn't initialized yet, do no processing - return; - } - - ASSERT(a_ItemGrid == &m_Contents); - switch (a_SlotNum) - { - case fsInput: - { - UpdateInput(); - break; - } - - case fsFuel: - { - UpdateFuel(); - break; - } - - case fsOutput: - { - UpdateOutput(); - break; - } - } -} - - - - - - -/// Updates the current recipe, based on the current input -void cFurnaceEntity::UpdateInput(void) -{ - if (!m_Contents.GetSlot(fsInput).IsStackableWith(m_LastInput)) - { - // The input is different from what we had before, reset the cooking time - m_TimeCooked = 0; - } - m_LastInput = m_Contents.GetSlot(fsInput); - - cFurnaceRecipe * FR = cRoot::Get()->GetFurnaceRecipe(); - m_CurrentRecipe = FR->GetRecipeFrom(m_Contents.GetSlot(fsInput)); - if (!CanCookInputToOutput()) - { - // This input cannot be cooked - m_NeedCookTime = 0; - SetIsCooking(false); - } - else - { - m_NeedCookTime = m_CurrentRecipe->CookTime; - SetIsCooking(true); - - // Start burning new fuel if there's no flame now: - if (GetFuelBurnTimeLeft() <= 0) - { - BurnNewFuel(); - } - } -} - - - - - -/// Called when the fuel slot changes or when the fuel is spent, burns another piece of fuel if appropriate -void cFurnaceEntity::UpdateFuel(void) -{ - if (m_FuelBurnTime > m_TimeBurned) - { - // The current fuel is still burning, don't modify anything: - return; - } - - // The current fuel is spent, try to burn some more: - BurnNewFuel(); -} - - - - - -/// Called when the output slot changes; starts burning if space became available -void cFurnaceEntity::UpdateOutput(void) -{ - if (!CanCookInputToOutput()) - { - // Cannot cook anymore: - m_TimeCooked = 0; - m_NeedCookTime = 0; - SetIsCooking(false); - return; - } - - // No need to burn new fuel, the Tick() function will take care of that - - // Can cook, start cooking if not already underway: - m_NeedCookTime = m_CurrentRecipe->CookTime; - SetIsCooking(m_FuelBurnTime > 0); -} - - - - - -/// Updates the m_IsCooking, based on the input slot, output slot and m_FuelBurnTime / m_TimeBurned -void cFurnaceEntity::UpdateIsCooking(void) -{ - if ( - !CanCookInputToOutput() || // Cannot cook this - (m_FuelBurnTime <= 0) || // No fuel - (m_TimeBurned >= m_FuelBurnTime) // Fuel burnt out - ) - { - // Reset everything - SetIsCooking(false); - m_TimeCooked = 0; - m_NeedCookTime = 0; - return; - } - - SetIsCooking(true); -} - - - - - -/// Returns true if the input can be cooked into output and the item counts allow for another cooking operation -bool cFurnaceEntity::CanCookInputToOutput(void) const -{ - if (m_CurrentRecipe == NULL) - { - // This input cannot be cooked - return false; - } - - if (m_Contents.GetSlot(fsOutput).IsEmpty()) - { - // The output is empty, can cook - return true; - } - - if (!m_Contents.GetSlot(fsOutput).IsStackableWith(*m_CurrentRecipe->Out)) - { - // The output slot is blocked with something that cannot be stacked with the recipe's output - return false; - } - - if (m_Contents.GetSlot(fsOutput).IsFullStack()) - { - // Cannot add any more items to the output slot - return false; - } - - return true; -} - - - - - -/// Broadcasts progressbar updates, if needed -void cFurnaceEntity::UpdateProgressBars(void) -{ - // In order to preserve bandwidth, an update is sent only every 10th tick - // That's why the comparisons use the division by eight - - int CurFuel = (m_FuelBurnTime > 0) ? (200 - 200 * m_TimeBurned / m_FuelBurnTime) : 0; - if ((CurFuel / 8) != (m_LastProgressFuel / 8)) - { - BroadcastProgress(PROGRESSBAR_FUEL, CurFuel); - m_LastProgressFuel = CurFuel; - } - - int CurCook = (m_NeedCookTime > 0) ? (200 * m_TimeCooked / m_NeedCookTime) : 0; - if ((CurCook / 8) != (m_LastProgressCook / 8)) - { - BroadcastProgress(PROGRESSBAR_SMELTING, CurCook); - m_LastProgressCook = CurCook; - } -} - - - - - -void cFurnaceEntity::SetIsCooking(bool a_IsCooking) -{ - if (a_IsCooking == m_IsCooking) - { - return; - } - - m_IsCooking = a_IsCooking; - - // Light or extinguish the furnace: - m_World->FastSetBlock(m_PosX, m_PosY, m_PosZ, m_IsCooking ? E_BLOCK_LIT_FURNACE : E_BLOCK_FURNACE, m_BlockMeta); -} - - - - diff --git a/source/BlockEntities/FurnaceEntity.h b/source/BlockEntities/FurnaceEntity.h deleted file mode 100644 index 9464fd175..000000000 --- a/source/BlockEntities/FurnaceEntity.h +++ /dev/null @@ -1,164 +0,0 @@ - -#pragma once - -#include "BlockEntityWithItems.h" -#include "../UI/WindowOwner.h" -#include "../FurnaceRecipe.h" - - - - - -namespace Json -{ - class Value; -} - -class cClientHandle; -class cServer; - - - - - -class cFurnaceEntity : // tolua_export - public cBlockEntityWindowOwner, - // tolua_begin - public cBlockEntityWithItems -{ - typedef cBlockEntityWithItems super; - -public: - enum - { - fsInput = 0, // Input slot number - fsFuel = 1, // Fuel slot number - fsOutput = 2, // Output slot number - - ContentsWidth = 3, - ContentsHeight = 1, - }; - - // tolua_end - - /// Constructor used for normal operation - cFurnaceEntity(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cWorld * a_World); - - virtual ~cFurnaceEntity(); - - static const char * GetClassStatic() { return "cFurnaceEntity"; } - - 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 bool Tick(float a_Dt, cChunk & a_Chunk) override; - virtual void UsedBy(cPlayer * a_Player) override; - - /// Restarts cooking. Used after the furnace is loaded from storage to set up the internal variables so that cooking continues, if it was active. Returns true if cooking. - bool ContinueCooking(void); - - void ResetCookTimer(); - - // tolua_begin - - /// Returns the item in the input slot - const cItem & GetInputSlot(void) const { return GetSlot(fsInput); } - - /// Returns the item in the fuel slot - const cItem & GetFuelSlot(void) const { return GetSlot(fsFuel); } - - /// Returns the item in the output slot - const cItem & GetOutputSlot(void) const { return GetSlot(fsOutput); } - - /// Sets the item in the input slot - void SetInputSlot(const cItem & a_Item) { SetSlot(fsInput, a_Item); } - - /// Sets the item in the fuel slot - void SetFuelSlot(const cItem & a_Item) { SetSlot(fsFuel, a_Item); } - - /// Sets the item in the output slot - void SetOutputSlot(const cItem & a_Item) { SetSlot(fsOutput, a_Item); } - - /// Returns the time that the current item has been cooking, in ticks - int GetTimeCooked(void) const {return m_TimeCooked; } - - /// Returns the time until the current item finishes cooking, in ticks - int GetCookTimeLeft(void) const { return m_NeedCookTime - m_TimeCooked; } - - /// Returns the time until the current fuel is depleted, in ticks - int GetFuelBurnTimeLeft(void) const {return m_FuelBurnTime - m_TimeBurned; } - - /// Returns true if there's time left before the current fuel is depleted - bool HasFuelTimeLeft(void) const { return (GetFuelBurnTimeLeft() > 0); } - - // tolua_end - - void SetBurnTimes(int a_FuelBurnTime, int a_TimeBurned) {m_FuelBurnTime = a_FuelBurnTime; m_TimeBurned = 0; } - void SetCookTimes(int a_NeedCookTime, int a_TimeCooked) {m_NeedCookTime = a_NeedCookTime; m_TimeCooked = a_TimeCooked; } - -protected: - - /// Block type of the block currently represented by this entity (changes when furnace lights up) - BLOCKTYPE m_BlockType; - - /// Block meta of the block currently represented by this entity - NIBBLETYPE m_BlockMeta; - - /// The recipe for the current input slot - const cFurnaceRecipe::Recipe * m_CurrentRecipe; - - /// The item that is being smelted - cItem m_LastInput; - - bool m_IsCooking; ///< Set to true if the furnace is cooking an item - - // All timers are in ticks - int m_NeedCookTime; ///< Amount of time needed to fully cook current item - int m_TimeCooked; ///< Amount of time that the current item has been cooking - int m_FuelBurnTime; ///< Amount of time that the current fuel can burn (in total); zero if no fuel burning - int m_TimeBurned; ///< Amount of time that the current fuel has been burning - - int m_LastProgressFuel; ///< Last value sent as the progress for the fuel - int m_LastProgressCook; ///< Last value sent as the progress for the cooking - - - /// Sends the specified progressbar value to all clients of the window - void BroadcastProgress(int a_ProgressbarID, short a_Value); - - /// One item finished cooking - void FinishOne(cChunk & a_Chunk); - - /// Starts burning a new fuel, if possible - void BurnNewFuel(void); - - /// Updates the recipe, based on the current input - void UpdateInput(void); - - /// Called when the fuel slot changes or when the fuel is spent, burns another piece of fuel if appropriate - void UpdateFuel(void); - - /// Called when the output slot changes - void UpdateOutput(void); - - /// Updates the m_IsCooking, based on the input slot, output slot and m_FuelBurnTime / m_TimeBurned - void UpdateIsCooking(void); - - /// Returns true if the input can be cooked into output and the item counts allow for another cooking operation - bool CanCookInputToOutput(void) const; - - /// Broadcasts progressbar updates, if needed - void UpdateProgressBars(void); - - /// Sets the m_IsCooking variable, updates the furnace block type based on the value - void SetIsCooking(bool a_IsCooking); - - // cItemGrid::cListener overrides: - virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override; - -} ; // tolua_export - - - - diff --git a/source/BlockEntities/HopperEntity.cpp b/source/BlockEntities/HopperEntity.cpp deleted file mode 100644 index 41849b1b3..000000000 --- a/source/BlockEntities/HopperEntity.cpp +++ /dev/null @@ -1,566 +0,0 @@ - -// HopperEntity.cpp - -// Implements the cHopperEntity representing a hopper block entity - -#include "Globals.h" -#include "HopperEntity.h" -#include "../Chunk.h" -#include "../Entities/Player.h" -#include "../PluginManager.h" -#include "ChestEntity.h" -#include "DropSpenserEntity.h" -#include "FurnaceEntity.h" - - - - - -cHopperEntity::cHopperEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) : - super(E_BLOCK_HOPPER, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World), - m_LastMoveItemsInTick(0), - m_LastMoveItemsOutTick(0) -{ -} - - - - - -/** Returns the block coords of the block receiving the output items, based on the meta -Returns false if unattached -*/ -bool cHopperEntity::GetOutputBlockPos(NIBBLETYPE a_BlockMeta, int & a_OutputX, int & a_OutputY, int & a_OutputZ) -{ - a_OutputX = m_PosX; - a_OutputY = m_PosY; - a_OutputZ = m_PosZ; - switch (a_BlockMeta) - { - case E_META_HOPPER_FACING_XM: a_OutputX--; return true; - case E_META_HOPPER_FACING_XP: a_OutputX++; return true; - case E_META_HOPPER_FACING_YM: a_OutputY--; return true; - case E_META_HOPPER_FACING_ZM: a_OutputZ--; return true; - case E_META_HOPPER_FACING_ZP: a_OutputZ++; return true; - default: - { - // Not attached - return false; - } - } -} - - - - - -bool cHopperEntity::Tick(float a_Dt, cChunk & a_Chunk) -{ - Int64 CurrentTick = a_Chunk.GetWorld()->GetWorldAge(); - - bool res = false; - res = MoveItemsIn (a_Chunk, CurrentTick) || res; - res = MovePickupsIn(a_Chunk, CurrentTick) || res; - res = MoveItemsOut (a_Chunk, CurrentTick) || res; - return res; -} - - - - - -void cHopperEntity::SaveToJson(Json::Value & a_Value) -{ - // TODO - LOGWARNING("%s: Not implemented yet", __FUNCTION__); -} - - - - - -void cHopperEntity::SendTo(cClientHandle & a_Client) -{ - // The hopper 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 hopper is rclked - - UNUSED(a_Client); -} - - - - - -void cHopperEntity::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); -} - - - - - -/// Opens a new window UI for this hopper -void cHopperEntity::OpenNewWindow(void) -{ - OpenWindow(new cHopperWindow(m_PosX, m_PosY, m_PosZ, this)); -} - - - - - -/// Moves items from the container above it into this hopper. Returns true if the contents have changed. -bool cHopperEntity::MoveItemsIn(cChunk & a_Chunk, Int64 a_CurrentTick) -{ - if (m_PosY >= cChunkDef::Height) - { - // This hopper is at the top of the world, no more blocks above - return false; - } - - if (a_CurrentTick - m_LastMoveItemsInTick < TICKS_PER_TRANSFER) - { - // Too early after the previous transfer - return false; - } - - // Try moving an item in: - bool res = false; - switch (a_Chunk.GetBlock(m_RelX, m_PosY + 1, m_RelZ)) - { - case E_BLOCK_CHEST: - { - // Chests have special handling because of double-chests - res = MoveItemsFromChest(a_Chunk); - break; - } - case E_BLOCK_LIT_FURNACE: - case E_BLOCK_FURNACE: - { - // Furnaces have special handling because only the output and leftover fuel buckets shall be moved - res = MoveItemsFromFurnace(a_Chunk); - break; - } - case E_BLOCK_DISPENSER: - case E_BLOCK_DROPPER: - case E_BLOCK_HOPPER: - { - res = MoveItemsFromGrid(*(cBlockEntityWithItems *)a_Chunk.GetBlockEntity(m_PosX, m_PosY + 1, m_PosZ)); - break; - } - } - - // If the item has been moved, reset the last tick: - if (res) - { - m_LastMoveItemsInTick = a_CurrentTick; - } - - return res; -} - - - - - -/// Moves pickups from above this hopper into it. Returns true if the contents have changed. -bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick) -{ - // TODO - return false; -} - - - - - -/// Moves items out from this hopper into the destination. Returns true if the contents have changed. -bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick) -{ - if (a_CurrentTick - m_LastMoveItemsOutTick < TICKS_PER_TRANSFER) - { - // Too early after the previous transfer - return false; - } - - int bx, by, bz; - NIBBLETYPE Meta = a_Chunk.GetMeta(m_RelX, m_PosY, m_RelZ); - if (!GetOutputBlockPos(Meta, bx, by, bz)) - { - // Not attached to another container - return false; - } - if (by < 0) - { - // Cannot output below the zero-th block level - return false; - } - - // Convert coords to relative: - int rx = bx - a_Chunk.GetPosX() * cChunkDef::Width; - int rz = bz - a_Chunk.GetPosZ() * cChunkDef::Width; - cChunk * DestChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(rx, rz); - if (DestChunk == NULL) - { - // The destination chunk has been unloaded, don't tick - return false; - } - - // Call proper moving function, based on the blocktype present at the coords: - bool res = false; - switch (DestChunk->GetBlock(rx, by, rz)) - { - case E_BLOCK_CHEST: - { - // Chests have special handling because of double-chests - res = MoveItemsToChest(*DestChunk, bx, by, bz); - break; - } - case E_BLOCK_LIT_FURNACE: - case E_BLOCK_FURNACE: - { - // Furnaces have special handling because of the direction-to-slot relation - res = MoveItemsToFurnace(*DestChunk, bx, by, bz, Meta); - break; - } - case E_BLOCK_DISPENSER: - case E_BLOCK_DROPPER: - case E_BLOCK_HOPPER: - { - res = MoveItemsToGrid(*(cBlockEntityWithItems *)DestChunk->GetBlockEntity(bx, by, bz)); - break; - } - } - - // If the item has been moved, reset the last tick: - if (res) - { - m_LastMoveItemsOutTick = a_CurrentTick; - } - - return res; -} - - - - - -/// Moves items from a chest (dblchest) above the hopper into this hopper. Returns true if contents have changed. -bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk) -{ - if (MoveItemsFromGrid(*(cChestEntity *)a_Chunk.GetBlockEntity(m_PosX, m_PosY + 1, m_PosZ))) - { - // Moved the item from the chest directly above the hopper - return true; - } - - // Check if the chest is a double-chest, if so, try to move from there: - static const struct - { - int x, z; - } - Coords [] = - { - {1, 0}, - {-1, 0}, - {0, 1}, - {0, -1}, - } ; - for (int i = 0; i < ARRAYCOUNT(Coords); i++) - { - int x = m_RelX + Coords[i].x; - int z = m_RelZ + Coords[i].z; - cChunk * Neighbor = a_Chunk.GetRelNeighborChunkAdjustCoords(x, z); - if ( - (Neighbor == NULL) || - (Neighbor->GetBlock(x, m_PosY + 1, z) != E_BLOCK_CHEST) - ) - { - continue; - } - if (MoveItemsFromGrid(*(cChestEntity *)Neighbor->GetBlockEntity(x, m_PosY, z))) - { - return true; - } - return false; - } - - // The chest was single and nothing could be moved - return false; -} - - - - - -/// Moves items from a furnace above the hopper into this hopper. Returns true if contents have changed. -bool cHopperEntity::MoveItemsFromFurnace(cChunk & a_Chunk) -{ - cFurnaceEntity * Furnace = (cFurnaceEntity *)a_Chunk.GetBlockEntity(m_PosX, m_PosY + 1, m_PosZ); - ASSERT(Furnace != NULL); - - // Try move from the output slot: - if (MoveItemsFromSlot(*Furnace, cFurnaceEntity::fsOutput, true)) - { - cItem NewOutput(Furnace->GetOutputSlot()); - Furnace->SetOutputSlot(NewOutput.AddCount(-1)); - return true; - } - - // No output moved, check if we can move an empty bucket out of the fuel slot: - if (Furnace->GetFuelSlot().m_ItemType == E_ITEM_BUCKET) - { - if (MoveItemsFromSlot(*Furnace, cFurnaceEntity::fsFuel, true)) - { - Furnace->SetFuelSlot(cItem()); - return true; - } - } - - // Nothing can be moved - return false; -} - - - - - -bool cHopperEntity::MoveItemsFromGrid(cBlockEntityWithItems & a_Entity) -{ - cItemGrid & Grid = a_Entity.GetContents(); - int NumSlots = Grid.GetNumSlots(); - - // First try adding items of types already in the hopper: - for (int i = 0; i < NumSlots; i++) - { - if (Grid.IsSlotEmpty(i)) - { - continue; - } - if (MoveItemsFromSlot(a_Entity, i, false)) - { - Grid.ChangeSlotCount(i, -1); - return true; - } - } - - // No already existing stack can be topped up, try again with allowing new stacks: - for (int i = 0; i < NumSlots; i++) - { - if (Grid.IsSlotEmpty(i)) - { - continue; - } - if (MoveItemsFromSlot(a_Entity, i, true)) - { - Grid.ChangeSlotCount(i, -1); - return true; - } - } - return false; -} - - - - - -/// Moves one piece of the specified a_Entity's slot itemstack into this hopper. Returns true if contents have changed. Doesn't change the itemstack. -bool cHopperEntity::MoveItemsFromSlot(cBlockEntityWithItems & a_Entity, int a_SlotNum, bool a_AllowNewStacks) -{ - cItem One(a_Entity.GetSlot(a_SlotNum).CopyOne()); - for (int i = 0; i < ContentsWidth * ContentsHeight; i++) - { - if (m_Contents.IsSlotEmpty(i)) - { - if (a_AllowNewStacks) - { - if (cPluginManager::Get()->CallHookHopperPullingItem(*m_World, *this, i, a_Entity, a_SlotNum)) - { - // Plugin disagrees with the move - continue; - } - } - m_Contents.SetSlot(i, One); - return true; - } - else if (m_Contents.GetSlot(i).IsStackableWith(One)) - { - if (cPluginManager::Get()->CallHookHopperPullingItem(*m_World, *this, i, a_Entity, a_SlotNum)) - { - // Plugin disagrees with the move - continue; - } - - m_Contents.ChangeSlotCount(i, 1); - return true; - } - } - return false; -} - - - - - -/// Moves items to the chest at the specified coords. Returns true if contents have changed -bool cHopperEntity::MoveItemsToChest(cChunk & a_Chunk, int a_BlockX, int a_BlockY, int a_BlockZ) -{ - // Try the chest directly connected to the hopper: - if (MoveItemsToGrid(*(cChestEntity *)a_Chunk.GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ))) - { - return true; - } - - // Check if the chest is a double-chest, if so, try to move into the other half: - static const struct - { - int x, z; - } - Coords [] = - { - {1, 0}, - {-1, 0}, - {0, 1}, - {0, -1}, - } ; - for (int i = 0; i < ARRAYCOUNT(Coords); i++) - { - int x = m_RelX + Coords[i].x; - int z = m_RelZ + Coords[i].z; - cChunk * Neighbor = a_Chunk.GetRelNeighborChunkAdjustCoords(x, z); - if ( - (Neighbor == NULL) || - (Neighbor->GetBlock(x, m_PosY + 1, z) != E_BLOCK_CHEST) - ) - { - continue; - } - if (MoveItemsToGrid(*(cChestEntity *)Neighbor->GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ))) - { - return true; - } - return false; - } - - // The chest was single and nothing could be moved - return false; -} - - - - - -/// Moves items to the furnace at the specified coords. Returns true if contents have changed -bool cHopperEntity::MoveItemsToFurnace(cChunk & a_Chunk, int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_HopperMeta) -{ - cFurnaceEntity * Furnace = (cFurnaceEntity *)a_Chunk.GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ); - if (a_HopperMeta == E_META_HOPPER_FACING_YM) - { - // Feed the input slot of the furnace - return MoveItemsToSlot(*Furnace, cFurnaceEntity::fsInput); - } - else - { - // Feed the fuel slot of the furnace - return MoveItemsToSlot(*Furnace, cFurnaceEntity::fsFuel); - } - return false; -} - - - - - -bool cHopperEntity::MoveItemsToGrid(cBlockEntityWithItems & a_Entity) -{ - // Iterate through our slots, try to move from each one: - int NumSlots = a_Entity.GetContents().GetNumSlots(); - for (int i = 0; i < NumSlots; i++) - { - if (MoveItemsToSlot(a_Entity, i)) - { - return true; - } - } - return false; -} - - - - - -bool cHopperEntity::MoveItemsToSlot(cBlockEntityWithItems & a_Entity, int a_DstSlotNum) -{ - cItemGrid & Grid = a_Entity.GetContents(); - if (Grid.IsSlotEmpty(a_DstSlotNum)) - { - // The slot is empty, move the first non-empty slot from our contents: - for (int i = 0; i < ContentsWidth * ContentsHeight; i++) - { - if (!m_Contents.IsSlotEmpty(i)) - { - if (cPluginManager::Get()->CallHookHopperPushingItem(*m_World, *this, i, a_Entity, a_DstSlotNum)) - { - // A plugin disagrees with the move - continue; - } - Grid.SetSlot(a_DstSlotNum, m_Contents.GetSlot(i).CopyOne()); - m_Contents.ChangeSlotCount(i, -1); - return true; - } - } - return false; - } - else - { - // The slot is taken, try to top it up: - const cItem & DestSlot = Grid.GetSlot(a_DstSlotNum); - if (DestSlot.IsFullStack()) - { - return false; - } - for (int i = 0; i < ContentsWidth * ContentsHeight; i++) - { - if (m_Contents.GetSlot(i).IsStackableWith(DestSlot)) - { - if (cPluginManager::Get()->CallHookHopperPushingItem(*m_World, *this, i, a_Entity, a_DstSlotNum)) - { - // A plugin disagrees with the move - continue; - } - Grid.ChangeSlotCount(a_DstSlotNum, 1); - m_Contents.ChangeSlotCount(i, -1); - return true; - } - } - return false; - } -} - - - - diff --git a/source/BlockEntities/HopperEntity.h b/source/BlockEntities/HopperEntity.h deleted file mode 100644 index 3eaa05b7c..000000000 --- a/source/BlockEntities/HopperEntity.h +++ /dev/null @@ -1,96 +0,0 @@ - -// HopperEntity.h - -// Declares the cHopperEntity representing a hopper block entity - - - - - -#pragma once - -#include "BlockEntityWithItems.h" -#include "../UI/WindowOwner.h" - - - - - -class cHopperEntity : // tolua_export - public cBlockEntityWindowOwner, - // tolua_begin - public cBlockEntityWithItems -{ - typedef cBlockEntityWithItems super; - -public: - enum { - ContentsHeight = 1, - ContentsWidth = 5, - TICKS_PER_TRANSFER = 8, ///< How many ticks at minimum between two item transfers to or from the hopper - } ; - - // tolua_end - - /// Constructor used for normal operation - cHopperEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World); - - /** Returns the block coords of the block receiving the output items, based on the meta - Returns false if unattached. - Exported in ManualBindings.cpp - */ - bool GetOutputBlockPos(NIBBLETYPE a_BlockMeta, int & a_OutputX, int & a_OutputY, int & a_OutputZ); - - static const char * GetClassStatic(void) { return "cHopperEntity"; } - -protected: - - Int64 m_LastMoveItemsInTick; - Int64 m_LastMoveItemsOutTick; - - // cBlockEntity overrides: - 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 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); - - /// Moves items from the container above it into this hopper. Returns true if the contents have changed. - bool MoveItemsIn(cChunk & a_Chunk, Int64 a_CurrentTick); - - /// Moves pickups from above this hopper into it. Returns true if the contents have changed. - bool MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick); - - /// Moves items out from this hopper into the destination. Returns true if the contents have changed. - bool MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick); - - /// Moves items from a chest (dblchest) above the hopper into this hopper. Returns true if contents have changed. - bool MoveItemsFromChest(cChunk & a_Chunk); - - /// Moves items from a furnace above the hopper into this hopper. Returns true if contents have changed. - bool MoveItemsFromFurnace(cChunk & a_Chunk); - - /// Moves items from the specified a_Entity's Contents into this hopper. Returns true if contents have changed. - bool MoveItemsFromGrid(cBlockEntityWithItems & a_Entity); - - /// Moves one piece from the specified itemstack into this hopper. Returns true if contents have changed. Doesn't change the itemstack. - bool MoveItemsFromSlot(cBlockEntityWithItems & a_Entity, int a_SrcSlotNum, bool a_AllowNewStacks); - - /// Moves items to the chest at the specified coords. Returns true if contents have changed - bool MoveItemsToChest(cChunk & a_Chunk, int a_BlockX, int a_BlockY, int a_BlockZ); - - /// Moves items to the furnace at the specified coords. Returns true if contents have changed - bool MoveItemsToFurnace(cChunk & a_Chunk, int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_HopperMeta); - - /// Moves items to the specified ItemGrid. Returns true if contents have changed - bool MoveItemsToGrid(cBlockEntityWithItems & a_Entity); - - /// Moves one piece to the specified entity's contents' slot. Returns true if contents have changed. - bool MoveItemsToSlot(cBlockEntityWithItems & a_Entity, int a_DstSlotNum); -} ; // tolua_export - - - - diff --git a/source/BlockEntities/JukeboxEntity.cpp b/source/BlockEntities/JukeboxEntity.cpp deleted file mode 100644 index aca376dd3..000000000 --- a/source/BlockEntities/JukeboxEntity.cpp +++ /dev/null @@ -1,125 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "JukeboxEntity.h" -#include "../World.h" -#include <json/json.h> - - - - - -cJukeboxEntity::cJukeboxEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) : - super(E_BLOCK_JUKEBOX, a_BlockX, a_BlockY, a_BlockZ, a_World), - m_Record(0) -{ -} - - - - - -cJukeboxEntity::~cJukeboxEntity() -{ - EjectRecord(); -} - - - - - -void cJukeboxEntity::UsedBy(cPlayer * a_Player) -{ - if (m_Record == 0) - { - const cItem & HeldItem = a_Player->GetEquippedItem(); - if (HeldItem.m_ItemType >= 2256 && HeldItem.m_ItemType <= 2267) - { - m_Record = HeldItem.m_ItemType; - a_Player->GetInventory().RemoveOneEquippedItem(); - PlayRecord(); - } - } - else - { - EjectRecord(); - } -} - - - - - -void cJukeboxEntity::PlayRecord(void) -{ - m_World->BroadcastSoundParticleEffect(1005, m_PosX, m_PosY, m_PosZ, m_Record); -} - - - - - -void cJukeboxEntity::EjectRecord(void) -{ - if ((m_Record < E_ITEM_FIRST_DISC) || (m_Record > E_ITEM_LAST_DISC)) - { - // There's no record here - return; - } - - cItems Drops; - Drops.push_back(cItem(m_Record, 1, 0)); - m_World->SpawnItemPickups(Drops, m_PosX + 0.5, m_PosY + 1, m_PosZ + 0.5, 8); - m_World->BroadcastSoundParticleEffect(1005, m_PosX, m_PosY, m_PosZ, 0); - m_Record = 0; -} - - - - - -int cJukeboxEntity::GetRecord(void) -{ - return m_Record; -} - - - - - -void cJukeboxEntity::SetRecord(int a_Record) -{ - m_Record = a_Record; -} - - - - - -bool cJukeboxEntity::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(); - - m_Record = a_Value.get("Record", 0).asInt(); - - return true; -} - - - - - -void cJukeboxEntity::SaveToJson(Json::Value & a_Value) -{ - a_Value["x"] = m_PosX; - a_Value["y"] = m_PosY; - a_Value["z"] = m_PosZ; - - a_Value["Record"] = m_Record; -} - - - - diff --git a/source/BlockEntities/JukeboxEntity.h b/source/BlockEntities/JukeboxEntity.h deleted file mode 100644 index fcafdc479..000000000 --- a/source/BlockEntities/JukeboxEntity.h +++ /dev/null @@ -1,56 +0,0 @@ - -#pragma once - -#include "BlockEntity.h" -#include "../Entities/Player.h" - - - - - -namespace Json -{ - class Value; -} - - - - - -// tolua_begin - -class cJukeboxEntity : - public cBlockEntity -{ - typedef cBlockEntity super; -public: - - // tolua_end - - cJukeboxEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World); - virtual ~cJukeboxEntity(); - - bool LoadFromJson(const Json::Value & a_Value); - virtual void SaveToJson(Json::Value & a_Value) override; - - // tolua_begin - - int GetRecord(void); - void SetRecord(int a_Record); - void PlayRecord(void); - - /// Ejects the currently held record as a pickup. Does nothing when no record inserted. - void EjectRecord(void); - - // tolua_end - - virtual void UsedBy(cPlayer * a_Player) override; - virtual void SendTo(cClientHandle & a_Client) override { }; - -private: - int m_Record; -} ; // tolua_end - - - - diff --git a/source/BlockEntities/NoteEntity.cpp b/source/BlockEntities/NoteEntity.cpp deleted file mode 100644 index 1b0620299..000000000 --- a/source/BlockEntities/NoteEntity.cpp +++ /dev/null @@ -1,154 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "NoteEntity.h" -#include "../World.h" -#include <json/json.h> - - - - - -cNoteEntity::cNoteEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) : - super(E_BLOCK_NOTE_BLOCK, a_BlockX, a_BlockY, a_BlockZ, a_World), - m_Pitch(0) -{ -} - - - - - -void cNoteEntity::UsedBy(cPlayer * a_Player) -{ - IncrementPitch(); - MakeSound(); -} - - - - - -void cNoteEntity::MakeSound(void) -{ - char instrument; - AString sampleName; - - switch (m_World->GetBlock(m_PosX, m_PosY - 1, m_PosZ)) - { - case E_BLOCK_PLANKS: - case E_BLOCK_LOG: - case E_BLOCK_NOTE_BLOCK: - { - // TODO: add other wood-based blocks if needed - instrument = E_INST_DOUBLE_BASS; - sampleName = "note.db"; - break; - } - - case E_BLOCK_SAND: - case E_BLOCK_GRAVEL: - case E_BLOCK_SOULSAND: - { - instrument = E_INST_SNARE_DRUM; - sampleName = "note.snare"; - break; - } - - case E_BLOCK_GLASS: - case E_BLOCK_GLASS_PANE: - case E_BLOCK_GLOWSTONE: - { - instrument = E_INST_CLICKS; - sampleName = "note.hat"; - break; - } - - case E_BLOCK_STONE: - case E_BLOCK_STONE_BRICKS: - case E_BLOCK_COBBLESTONE: - case E_BLOCK_OBSIDIAN: - case E_BLOCK_NETHERRACK: - case E_BLOCK_BRICK: - case E_BLOCK_NETHER_BRICK: - { - // TODO: add other stone-based blocks if needed - instrument = E_INST_BASS_DRUM; - sampleName = "note.bassattack"; - break; - } - - default: - { - instrument = E_INST_HARP_PIANO; - sampleName = "note.harp"; - break; - } - } - - m_World->BroadcastBlockAction(m_PosX, m_PosY, m_PosZ, instrument, m_Pitch, E_BLOCK_NOTE_BLOCK); - - // TODO: instead of calculating the power function over and over, make a precalculated table - there's only 24 pitches after all - float calcPitch = pow(2.0f, ((float)m_Pitch - 12.0f) / 12.0f); - m_World->BroadcastSoundEffect(sampleName, m_PosX * 8, m_PosY * 8, m_PosZ * 8, 3.0f, calcPitch); -} - - - - - -char cNoteEntity::GetPitch(void) -{ - return m_Pitch; -} - - - - - -void cNoteEntity::SetPitch(char a_Pitch) -{ - m_Pitch = a_Pitch % 25; -} - - - - - -void cNoteEntity::IncrementPitch(void) -{ - SetPitch(m_Pitch + 1); -} - - - - - -bool cNoteEntity::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(); - - m_Pitch = (char)a_Value.get("p", 0).asInt(); - - return true; -} - - - - - -void cNoteEntity::SaveToJson(Json::Value & a_Value) -{ - a_Value["x"] = m_PosX; - a_Value["y"] = m_PosY; - a_Value["z"] = m_PosZ; - - a_Value["p"] = m_Pitch; -} - - - - diff --git a/source/BlockEntities/NoteEntity.h b/source/BlockEntities/NoteEntity.h deleted file mode 100644 index e2d088f44..000000000 --- a/source/BlockEntities/NoteEntity.h +++ /dev/null @@ -1,63 +0,0 @@ - -#pragma once - -#include "BlockEntity.h" - - -namespace Json -{ - class Value; -} - - - - - -enum ENUM_NOTE_INSTRUMENTS -{ - E_INST_HARP_PIANO = 0, - E_INST_DOUBLE_BASS = 1, - E_INST_SNARE_DRUM = 2, - E_INST_CLICKS = 3, - E_INST_BASS_DRUM = 4 -}; - - - - - -// tolua_begin - -class cNoteEntity : - public cBlockEntity -{ - typedef cBlockEntity super; -public: - - // tolua_end - - /// Creates a new note entity. a_World may be NULL - cNoteEntity(int a_X, int a_Y, int a_Z, cWorld * a_World); - - bool LoadFromJson(const Json::Value & a_Value); - virtual void SaveToJson(Json::Value & a_Value) override; - - // tolua_begin - - char GetPitch(void); - void SetPitch(char a_Pitch); - void IncrementPitch(void); - void MakeSound(void); - - // tolua_end - - virtual void UsedBy(cPlayer * a_Player) override; - virtual void SendTo(cClientHandle & a_Client) override { }; - -private: - char m_Pitch; -} ; // tolua_export - - - - diff --git a/source/BlockEntities/SignEntity.cpp b/source/BlockEntities/SignEntity.cpp deleted file mode 100644 index 81f6f6d77..000000000 --- a/source/BlockEntities/SignEntity.cpp +++ /dev/null @@ -1,115 +0,0 @@ - -// SignEntity.cpp - -// Implements the cSignEntity class representing a single sign in the world - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules -#include <json/json.h> -#include "SignEntity.h" -#include "../Entities/Player.h" - - - - - -cSignEntity::cSignEntity(BLOCKTYPE a_BlockType, int a_X, int a_Y, int a_Z, cWorld * a_World) : - super(a_BlockType, a_X, a_Y, a_Z, a_World) -{ -} - - - - - -// It don't do anything when 'used' -void cSignEntity::UsedBy(cPlayer * a_Player) -{ - UNUSED(a_Player); -} - - - - - -void cSignEntity::SetLines(const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) -{ - m_Line[0] = a_Line1; - m_Line[1] = a_Line2; - m_Line[2] = a_Line3; - m_Line[3] = a_Line4; -} - - - - - -void cSignEntity::SetLine(int a_Index, const AString & a_Line) -{ - if ((a_Index < 0) || (a_Index >= ARRAYCOUNT(m_Line))) - { - LOGWARNING("%s: setting a non-existent line %d (value \"%s\"", __FUNCTION__, a_Index, a_Line.c_str()); - return; - } - m_Line[a_Index] = a_Line; -} - - - - - -AString cSignEntity::GetLine(int a_Index) const -{ - if ((a_Index < 0) || (a_Index >= ARRAYCOUNT(m_Line))) - { - LOGWARNING("%s: requesting a non-existent line %d", __FUNCTION__, a_Index); - return ""; - } - return m_Line[a_Index]; -} - - - - - -void cSignEntity::SendTo(cClientHandle & a_Client) -{ - a_Client.SendUpdateSign(m_PosX, m_PosY, m_PosZ, m_Line[0], m_Line[1], m_Line[2], m_Line[3]); -} - - - - - -bool cSignEntity::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(); - - m_Line[0] = a_Value.get("Line1", "").asString(); - m_Line[1] = a_Value.get("Line2", "").asString(); - m_Line[2] = a_Value.get("Line3", "").asString(); - m_Line[3] = a_Value.get("Line4", "").asString(); - - return true; -} - - - - - -void cSignEntity::SaveToJson(Json::Value & a_Value) -{ - a_Value["x"] = m_PosX; - a_Value["y"] = m_PosY; - a_Value["z"] = m_PosZ; - - a_Value["Line1"] = m_Line[0]; - a_Value["Line2"] = m_Line[1]; - a_Value["Line3"] = m_Line[2]; - a_Value["Line4"] = m_Line[3]; -} - - - - diff --git a/source/BlockEntities/SignEntity.h b/source/BlockEntities/SignEntity.h deleted file mode 100644 index d998ff1e8..000000000 --- a/source/BlockEntities/SignEntity.h +++ /dev/null @@ -1,67 +0,0 @@ - -// SignEntity.h - -// Declares the cSignEntity class representing a single sign in the world - - - - - -#pragma once - -#include "BlockEntity.h" - - - - - -namespace Json -{ - class Value; -} - - - - - -// tolua_begin - -class cSignEntity : - public cBlockEntity -{ - typedef cBlockEntity super; - -public: - - // tolua_end - - /// Creates a new empty sign entity at the specified block coords and block type (wall or standing). a_World may be NULL - cSignEntity(BLOCKTYPE a_BlockType, int a_X, int a_Y, int a_Z, cWorld * a_World); - - bool LoadFromJson( const Json::Value& a_Value ); - virtual void SaveToJson(Json::Value& a_Value ) override; - - // tolua_begin - - /// Sets all the sign's lines - void SetLines(const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4); - - /// Sets individual line (zero-based index) - void SetLine(int a_Index, const AString & a_Line); - - /// Retrieves individual line (zero-based index) - AString GetLine(int a_Index) const; - - // tolua_end - - virtual void UsedBy(cPlayer * a_Player) override; - virtual void SendTo(cClientHandle & a_Client) override; - -private: - - AString m_Line[4]; -} ; // tolua_export - - - - |