Implemented hopper output
git-svn-id: http://mc-server.googlecode.com/svn/trunk@1611 0a769ca7-a7f5-676a-18bf-c427514a06d6master
parent
d633f8a671
commit
512c342782
|
@ -16,7 +16,9 @@
|
|||
|
||||
|
||||
cHopperEntity::cHopperEntity(int a_BlockX, int a_BlockY, int a_BlockZ) :
|
||||
super(E_BLOCK_HOPPER, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, NULL)
|
||||
super(E_BLOCK_HOPPER, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, NULL),
|
||||
m_LastMoveItemsInTick(0),
|
||||
m_LastMoveItemsOutTick(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -25,7 +27,9 @@ cHopperEntity::cHopperEntity(int a_BlockX, int a_BlockY, int a_BlockZ) :
|
|||
|
||||
|
||||
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)
|
||||
super(E_BLOCK_HOPPER, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World),
|
||||
m_LastMoveItemsInTick(0),
|
||||
m_LastMoveItemsOutTick(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -33,6 +37,33 @@ cHopperEntity::cHopperEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld *
|
|||
|
||||
|
||||
|
||||
/** 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();
|
||||
|
@ -171,8 +202,47 @@ bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick)
|
|||
return false;
|
||||
}
|
||||
|
||||
// TODO
|
||||
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: res = MoveItemsToChest(*DestChunk, bx, by, bz); break;
|
||||
case E_BLOCK_FURNACE: 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;
|
||||
}
|
||||
|
||||
// If the item has been moved, reset the last tick:
|
||||
if (res)
|
||||
{
|
||||
m_LastMoveItemsOutTick = a_CurrentTick;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
@ -312,3 +382,140 @@ bool cHopperEntity::MoveItemsFromSlot(const cItem & a_ItemStack, bool a_AllowNew
|
|||
|
||||
|
||||
|
||||
|
||||
/// 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 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->GetContents(), cFurnaceEntity::fsInput);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Feed the fuel slot of the furnace
|
||||
return MoveItemsToSlot(Furnace->GetContents(), cFurnaceEntity::fsFuel);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Moves items to the specified ItemGrid. Returns true if contents have changed
|
||||
bool cHopperEntity::MoveItemsToGrid(cItemGrid & a_ItemGrid)
|
||||
{
|
||||
// Iterate through our slots, try to move from each one:
|
||||
for (int i = 0; i < ContentsWidth * ContentsHeight; i++)
|
||||
{
|
||||
const cItem & SrcItem = m_Contents.GetSlot(i);
|
||||
if (SrcItem.IsEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
cItem ToAdd = SrcItem.CopyOne();
|
||||
if (a_ItemGrid.AddItem(ToAdd) > 0)
|
||||
{
|
||||
m_Contents.ChangeSlotCount(i, -1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Moves one piece to the specified ItemGrid's slot. Returns true if contents have changed.
|
||||
bool cHopperEntity::MoveItemsToSlot(cItemGrid & a_ItemGrid, int a_DestSlotNum)
|
||||
{
|
||||
if (a_ItemGrid.IsSlotEmpty(a_DestSlotNum))
|
||||
{
|
||||
// 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());
|
||||
m_Contents.ChangeSlotCount(i, -1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The slot is taken, try to top it up:
|
||||
const cItem & DestSlot = a_ItemGrid.GetSlot(a_DestSlotNum);
|
||||
if (DestSlot.IsFullStack())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < ContentsWidth * ContentsHeight; i++)
|
||||
{
|
||||
if (m_Contents.GetSlot(i).IsStackableWith(DestSlot))
|
||||
{
|
||||
a_ItemGrid.ChangeSlotCount(a_DestSlotNum, 1);
|
||||
m_Contents.ChangeSlotCount(i, -1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -38,6 +38,15 @@ public:
|
|||
/// Constructor used for normal operation
|
||||
cHopperEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
|
||||
|
||||
// tolua_begin
|
||||
|
||||
/** Returns the block coords of the block receiving the output items, based on the meta
|
||||
Returns false if unattached
|
||||
*/
|
||||
bool GetOutputBlockPos(NIBBLETYPE a_BlockMeta, int & a_OutputX, int & a_OutputY, int & a_OutputZ);
|
||||
|
||||
// tolua_end
|
||||
|
||||
static const char * GetClassStatic(void) { return "cHopperEntity"; }
|
||||
|
||||
protected:
|
||||
|
@ -72,8 +81,20 @@ protected:
|
|||
/// Moves items from the specified ItemGrid into this hopper. Returns true if contents have changed.
|
||||
bool MoveItemsFromGrid(cItemGrid & a_Grid);
|
||||
|
||||
/// Moves one of the specified itemstack into this hopper. Returns true if contents have changed. Doesn't change the itemstack.
|
||||
/// 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);
|
||||
|
||||
/// 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(cItemGrid & a_ItemGrid);
|
||||
|
||||
/// Moves one piece to the specified ItemGrid's slot. Returns true if contents have changed.
|
||||
bool MoveItemsToSlot(cItemGrid & a_ItemGrid, int a_DestSlotNum);
|
||||
} ;
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue