Implemented hopper output
git-svn-id: http://mc-server.googlecode.com/svn/trunk@1611 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
d633f8a671
commit
512c342782
@ -16,7 +16,9 @@
|
|||||||
|
|
||||||
|
|
||||||
cHopperEntity::cHopperEntity(int a_BlockX, int a_BlockY, int a_BlockZ) :
|
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) :
|
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)
|
bool cHopperEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
Int64 CurrentTick = a_Chunk.GetWorld()->GetWorldAge();
|
Int64 CurrentTick = a_Chunk.GetWorld()->GetWorldAge();
|
||||||
@ -171,8 +202,47 @@ bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
int bx, by, bz;
|
||||||
return false;
|
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
|
/// Constructor used for normal operation
|
||||||
cHopperEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
|
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"; }
|
static const char * GetClassStatic(void) { return "cHopperEntity"; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -72,8 +81,20 @@ protected:
|
|||||||
/// Moves items from the specified ItemGrid into this hopper. Returns true if contents have changed.
|
/// Moves items from the specified ItemGrid into this hopper. Returns true if contents have changed.
|
||||||
bool MoveItemsFromGrid(cItemGrid & a_Grid);
|
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);
|
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…
x
Reference in New Issue
Block a user