From dd60f55bccd603650906d5025f689a82d00b3718 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 11 Aug 2013 14:57:07 +0200 Subject: Added the OnHopperPullingItem and OnHopperPushingItem hooks. Requested in FS 412, slightly modified the params. --- source/BlockEntities/HopperEntity.cpp | 154 +++++++++++++++++++++++----------- source/BlockEntities/HopperEntity.h | 12 +-- 2 files changed, 110 insertions(+), 56 deletions(-) (limited to 'source/BlockEntities') diff --git a/source/BlockEntities/HopperEntity.cpp b/source/BlockEntities/HopperEntity.cpp index 591db7b4d..6fdff0e70 100644 --- a/source/BlockEntities/HopperEntity.cpp +++ b/source/BlockEntities/HopperEntity.cpp @@ -7,6 +7,7 @@ #include "HopperEntity.h" #include "../Chunk.h" #include "../Player.h" +#include "../PluginManager.h" #include "ChestEntity.h" #include "DropSpenserEntity.h" #include "FurnaceEntity.h" @@ -162,12 +163,26 @@ bool cHopperEntity::MoveItemsIn(cChunk & a_Chunk, Int64 a_CurrentTick) bool res = false; switch (a_Chunk.GetBlock(m_RelX, m_PosY + 1, m_RelZ)) { - case E_BLOCK_CHEST: res = MoveItemsFromChest(a_Chunk); break; - case E_BLOCK_FURNACE: res = MoveItemsFromFurnace(a_Chunk); break; + 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: res = MoveItemsFromGrid(((cDropSpenserEntity *)a_Chunk.GetBlockEntity(m_PosX, m_PosY + 1, m_PosZ))->GetContents()); break; - case E_BLOCK_HOPPER: res = MoveItemsFromGrid(((cHopperEntity *) a_Chunk.GetBlockEntity(m_PosX, m_PosY + 1, m_PosZ))->GetContents()); break; - case E_BLOCK_LIT_FURNACE: res = MoveItemsFromFurnace(a_Chunk); break; + 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: @@ -230,12 +245,26 @@ bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick) bool res = false; switch (DestChunk->GetBlock(rx, by, rz)) { - case E_BLOCK_CHEST: res = MoveItemsToChest(*DestChunk, bx, by, bz); break; - case E_BLOCK_FURNACE: res = MoveItemsToFurnace(*DestChunk, bx, by, bz, Meta); break; + 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: res = MoveItemsToGrid(((cDropSpenserEntity *)DestChunk->GetBlockEntity(bx, by, bz))->GetContents()); break; - case E_BLOCK_HOPPER: res = MoveItemsToGrid(((cHopperEntity *) DestChunk->GetBlockEntity(bx, by, bz))->GetContents()); break; - case E_BLOCK_LIT_FURNACE: res = MoveItemsToFurnace(*DestChunk, bx, by, bz, Meta); break; + 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: @@ -254,7 +283,7 @@ bool cHopperEntity::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 cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk) { - if (MoveItemsFromGrid(((cChestEntity *)a_Chunk.GetBlockEntity(m_PosX, m_PosY + 1, m_PosZ))->GetContents())) + 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; @@ -284,7 +313,7 @@ bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk) { continue; } - if (MoveItemsFromGrid(((cChestEntity *)Neighbor->GetBlockEntity(x, m_PosY, z))->GetContents())) + if (MoveItemsFromGrid(*(cChestEntity *)Neighbor->GetBlockEntity(x, m_PosY, z))) { return true; } @@ -306,7 +335,7 @@ bool cHopperEntity::MoveItemsFromFurnace(cChunk & a_Chunk) ASSERT(Furnace != NULL); // Try move from the output slot: - if (MoveItemsFromSlot(Furnace->GetOutputSlot(), true)) + if (MoveItemsFromSlot(*Furnace, cFurnaceEntity::fsOutput, true)) { cItem NewOutput(Furnace->GetOutputSlot()); Furnace->SetOutputSlot(NewOutput.AddCount(-1)); @@ -316,7 +345,7 @@ bool cHopperEntity::MoveItemsFromFurnace(cChunk & a_Chunk) // 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->GetFuelSlot(), true)) + if (MoveItemsFromSlot(*Furnace, cFurnaceEntity::fsFuel, true)) { Furnace->SetFuelSlot(cItem()); return true; @@ -331,21 +360,21 @@ bool cHopperEntity::MoveItemsFromFurnace(cChunk & a_Chunk) -/// Moves items from the specified ItemGrid into this hopper. Returns true if contents have changed. -bool cHopperEntity::MoveItemsFromGrid(cItemGrid & a_Grid) +bool cHopperEntity::MoveItemsFromGrid(cBlockEntityWithItems & a_Entity) { - int NumSlots = a_Grid.GetNumSlots(); + 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 (a_Grid.IsSlotEmpty(i)) + if (Grid.IsSlotEmpty(i)) { continue; } - if (MoveItemsFromSlot(a_Grid.GetSlot(i), false)) + if (MoveItemsFromSlot(a_Entity, i, false)) { - a_Grid.ChangeSlotCount(i, -1); + Grid.ChangeSlotCount(i, -1); return true; } } @@ -353,13 +382,13 @@ bool cHopperEntity::MoveItemsFromGrid(cItemGrid & a_Grid) // No already existing stack can be topped up, try again with allowing new stacks: for (int i = 0; i < NumSlots; i++) { - if (a_Grid.IsSlotEmpty(i)) + if (Grid.IsSlotEmpty(i)) { continue; } - if (MoveItemsFromSlot(a_Grid.GetSlot(i), true)) + if (MoveItemsFromSlot(a_Entity, i, true)) { - a_Grid.ChangeSlotCount(i, -1); + Grid.ChangeSlotCount(i, -1); return true; } } @@ -370,13 +399,36 @@ bool cHopperEntity::MoveItemsFromGrid(cItemGrid & a_Grid) -/// Moves one of the specified itemstack into this hopper. Returns true if contents have changed. Doesn't change the itemstack. -bool cHopperEntity::MoveItemsFromSlot(const cItem & a_ItemStack, bool a_AllowNewStacks) +/// 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_ItemStack.CopyOne()); - if (m_Contents.AddItem(One, a_AllowNewStacks) > 0) + cItem One(a_Entity.GetSlot(a_SlotNum).CopyOne()); + for (int i = 0; i < ContentsWidth * ContentsHeight; i++) { - return true; + 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; } @@ -389,7 +441,7 @@ bool cHopperEntity::MoveItemsFromSlot(const cItem & a_ItemStack, bool a_AllowNew 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))->GetContents())) + if (MoveItemsToGrid(*(cChestEntity *)a_Chunk.GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ))) { return true; } @@ -418,7 +470,7 @@ bool cHopperEntity::MoveItemsToChest(cChunk & a_Chunk, int a_BlockX, int a_Block { continue; } - if (MoveItemsToGrid(((cChestEntity *)Neighbor->GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ))->GetContents())) + if (MoveItemsToGrid(*(cChestEntity *)Neighbor->GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ))) { return true; } @@ -440,12 +492,12 @@ bool cHopperEntity::MoveItemsToFurnace(cChunk & a_Chunk, int a_BlockX, int a_Blo if (a_HopperMeta == E_META_HOPPER_FACING_YM) { // Feed the input slot of the furnace - return MoveItemsToSlot(Furnace->GetContents(), cFurnaceEntity::fsInput); + return MoveItemsToSlot(*Furnace, cFurnaceEntity::fsInput); } else { // Feed the fuel slot of the furnace - return MoveItemsToSlot(Furnace->GetContents(), cFurnaceEntity::fsFuel); + return MoveItemsToSlot(*Furnace, cFurnaceEntity::fsFuel); } return false; } @@ -454,22 +506,14 @@ bool cHopperEntity::MoveItemsToFurnace(cChunk & a_Chunk, int a_BlockX, int a_Blo -/// Moves items to the specified ItemGrid. Returns true if contents have changed -bool cHopperEntity::MoveItemsToGrid(cItemGrid & a_ItemGrid) +bool cHopperEntity::MoveItemsToGrid(cBlockEntityWithItems & a_Entity) { // Iterate through our slots, try to move from each one: - for (int i = 0; i < ContentsWidth * ContentsHeight; i++) + int NumSlots = a_Entity.GetContents().GetNumSlots(); + for (int i = 0; i < NumSlots; i++) { - const cItem & SrcItem = m_Contents.GetSlot(i); - if (SrcItem.IsEmpty()) - { - continue; - } - - cItem ToAdd = SrcItem.CopyOne(); - if (a_ItemGrid.AddItem(ToAdd) > 0) + if (MoveItemsToSlot(a_Entity, i)) { - m_Contents.ChangeSlotCount(i, -1); return true; } } @@ -480,17 +524,22 @@ bool cHopperEntity::MoveItemsToGrid(cItemGrid & a_ItemGrid) -/// Moves one piece to the specified ItemGrid's slot. Returns true if contents have changed. -bool cHopperEntity::MoveItemsToSlot(cItemGrid & a_ItemGrid, int a_DestSlotNum) +bool cHopperEntity::MoveItemsToSlot(cBlockEntityWithItems & a_Entity, int a_DstSlotNum) { - if (a_ItemGrid.IsSlotEmpty(a_DestSlotNum)) + 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)) { - a_ItemGrid.SetSlot(a_DestSlotNum, m_Contents.GetSlot(i).CopyOne()); + 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; } @@ -500,7 +549,7 @@ bool cHopperEntity::MoveItemsToSlot(cItemGrid & a_ItemGrid, int a_DestSlotNum) else { // The slot is taken, try to top it up: - const cItem & DestSlot = a_ItemGrid.GetSlot(a_DestSlotNum); + const cItem & DestSlot = Grid.GetSlot(a_DstSlotNum); if (DestSlot.IsFullStack()) { return false; @@ -509,7 +558,12 @@ bool cHopperEntity::MoveItemsToSlot(cItemGrid & a_ItemGrid, int a_DestSlotNum) { if (m_Contents.GetSlot(i).IsStackableWith(DestSlot)) { - a_ItemGrid.ChangeSlotCount(a_DestSlotNum, 1); + 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; } diff --git a/source/BlockEntities/HopperEntity.h b/source/BlockEntities/HopperEntity.h index 8fc17b631..a49868660 100644 --- a/source/BlockEntities/HopperEntity.h +++ b/source/BlockEntities/HopperEntity.h @@ -78,11 +78,11 @@ protected: /// 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 ItemGrid into this hopper. Returns true if contents have changed. - bool MoveItemsFromGrid(cItemGrid & a_Grid); + /// 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(const cItem & a_ItemStack, bool a_AllowNewStacks); + 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); @@ -91,10 +91,10 @@ protected: 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(cItemGrid & a_ItemGrid); + bool MoveItemsToGrid(cBlockEntityWithItems & a_Entity); - /// Moves one piece to the specified ItemGrid's slot. Returns true if contents have changed. - bool MoveItemsToSlot(cItemGrid & a_ItemGrid, int a_DestSlotNum); + /// Moves one piece to the specified entity's contents' slot. Returns true if contents have changed. + bool MoveItemsToSlot(cBlockEntityWithItems & a_Entity, int a_DstSlotNum); } ; -- cgit v1.2.3