/// 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->GetOutputSlot(), 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->GetFuelSlot(), true)) { Furnace->SetFuelSlot(cItem()); return true; } } // Nothing can be moved return false; }
/// 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: res = MoveItemsFromChest(a_Chunk); break; case E_BLOCK_FURNACE: 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; } // If the item has been moved, reset the last tick: if (res) { m_LastMoveItemsInTick = a_CurrentTick; } return res; }
/// 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); if (Furnace == NULL) { LOGWARNING("%s: A furnace entity was not found where expected, at {%d, %d, %d}", __FUNCTION__, m_PosX, m_PosY + 1, m_PosZ); return false; } // 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; }
/// 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); } }
/// 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_TRAPPED_CHEST: 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 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))->GetContents())) { 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))->GetContents())) { return true; } return false; } // The chest was single and nothing could be moved return false; }
/// 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())) { // 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))->GetContents())) { return true; } return false; } // The chest was single and nothing could be moved 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: cChestEntity * ConnectedChest = (cChestEntity *)a_Chunk.GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ); if (ConnectedChest == NULL) { LOGWARNING("%s: A chest entity was not found where expected, at {%d, %d, %d}", __FUNCTION__, a_BlockX, a_BlockY, a_BlockZ); return false; } if (MoveItemsToGrid(*ConnectedChest)) { // Chest block directly connected was not full return true; } // Check if the chest is a double-chest (chest block directly connected was full), if so, try to move into the other half: static const struct { int x, z; } Coords [] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1}, } ; int RelX = a_BlockX - a_Chunk.GetPosX() * cChunkDef::Width; int RelZ = a_BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width; for (size_t i = 0; i < ARRAYCOUNT(Coords); i++) { int x = RelX + Coords[i].x; int z = RelZ + Coords[i].z; cChunk * Neighbor = a_Chunk.GetRelNeighborChunkAdjustCoords(x, z); if (Neighbor == NULL) { continue; } BLOCKTYPE Block = Neighbor->GetBlock(x, a_BlockY, z); if (Block != ConnectedChest->GetBlockType()) { // Not the same kind of chest continue; } cChestEntity * Chest = (cChestEntity *)Neighbor->GetBlockEntity(a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z); if (Chest == NULL) { LOGWARNING("%s: A chest entity was not found where expected, at {%d, %d, %d} (%d, %d)", __FUNCTION__, a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z, x, z); continue; } if (MoveItemsToGrid(*Chest)) { return true; } return false; } // The chest was single and nothing could be moved return false; }
/// Moves items from a chest (dblchest) above the hopper into this hopper. Returns true if contents have changed. bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk) { cChestEntity * MainChest = (cChestEntity *)a_Chunk.GetBlockEntity(m_PosX, m_PosY + 1, m_PosZ); if (MainChest == NULL) { LOGWARNING("%s: A chest entity was not found where expected, at {%d, %d, %d}", __FUNCTION__, m_PosX, m_PosY + 1, m_PosZ); return false; } if (MoveItemsFromGrid(*MainChest)) { // Moved the item from the chest directly above the hopper return true; } // Check if the chest is a double-chest (chest directly above was empty), if so, try to move from there: static const struct { int x, z; } Coords [] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1}, } ; for (size_t 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) { continue; } BLOCKTYPE Block = Neighbor->GetBlock(x, m_PosY + 1, z); if (Block != MainChest->GetBlockType()) { // Not the same kind of chest continue; } cChestEntity * SideChest = (cChestEntity *)Neighbor->GetBlockEntity(m_PosX + Coords[i].x, m_PosY + 1, m_PosZ + Coords[i].z); if (SideChest == NULL) { LOGWARNING("%s: A chest entity was not found where expected, at {%d, %d, %d}", __FUNCTION__, m_PosX + Coords[i].x, m_PosY + 1, m_PosZ + Coords[i].z); } else { if (MoveItemsFromGrid(*SideChest)) { return true; } } return false; } // The chest was single and nothing could be moved return false; }