本文整理汇总了C++中cChunk::GetRelNeighborChunkAdjustCoords方法的典型用法代码示例。如果您正苦于以下问题:C++ cChunk::GetRelNeighborChunkAdjustCoords方法的具体用法?C++ cChunk::GetRelNeighborChunkAdjustCoords怎么用?C++ cChunk::GetRelNeighborChunkAdjustCoords使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类cChunk
的用法示例。
在下文中一共展示了cChunk::GetRelNeighborChunkAdjustCoords方法的13个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: Tick
void cArrowEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
if (!IsTicking())
{
// The base class tick destroyed us
return;
}
m_Timer += a_Dt;
if (m_bIsCollected)
{
if (m_Timer > std::chrono::milliseconds(500))
{
Destroy();
return;
}
}
else if (m_Timer > std::chrono::minutes(5))
{
Destroy();
return;
}
if (m_IsInGround)
{
if (!m_HasTeleported) // Sent a teleport already, don't do again
{
if (m_HitGroundTimer > std::chrono::milliseconds(500))
{
m_World->BroadcastTeleportEntity(*this);
m_HasTeleported = true;
}
else
{
m_HitGroundTimer += a_Dt;
}
}
int RelPosX = m_HitBlockPos.x - a_Chunk.GetPosX() * cChunkDef::Width;
int RelPosZ = m_HitBlockPos.z - a_Chunk.GetPosZ() * cChunkDef::Width;
cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelPosX, RelPosZ);
if (Chunk == nullptr)
{
// Inside an unloaded chunk, abort
return;
}
if (Chunk->GetBlock(RelPosX, m_HitBlockPos.y, RelPosZ) == E_BLOCK_AIR) // Block attached to was destroyed?
{
m_IsInGround = false; // Yes, begin simulating physics again
}
}
}
示例2: Tick
void cArrowEntity::Tick(float a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
m_Timer += a_Dt;
if (m_bIsCollected)
{
if (m_Timer > 500.f) // 0.5 seconds
{
Destroy();
return;
}
}
else if (m_Timer > 1000 * 60 * 5) // 5 minutes
{
Destroy();
return;
}
if (m_IsInGround)
{
// When an arrow hits, the client doesn't think its in the ground and keeps on moving, IF BroadcastMovementUpdate() and TeleportEntity was called during flight, AT ALL
// Fix is to simply not sync with the client and send a teleport to confirm pos after arrow has stabilised (around 1 sec after landing)
// We can afford to do this because xoft's algorithm for trajectory is near perfect, so things are pretty close anyway without sync
// Besides, this seems to be what the vanilla server does, note how arrows teleport half a second after they hit to the server position
if (m_HitGroundTimer != -1) // Sent a teleport already, don't do again
{
if (m_HitGroundTimer > 1000.f) // Send after a second, could be less, but just in case
{
m_World->BroadcastTeleportEntity(*this);
m_HitGroundTimer = -1;
}
else
{
m_HitGroundTimer += a_Dt;
}
}
int RelPosX = m_HitBlockPos.x - a_Chunk.GetPosX() * cChunkDef::Width;
int RelPosZ = m_HitBlockPos.z - a_Chunk.GetPosZ() * cChunkDef::Width;
cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelPosX, RelPosZ);
if (Chunk == NULL)
{
// Inside an unloaded chunk, abort
return;
}
if (Chunk->GetBlock(RelPosX, m_HitBlockPos.y, RelPosZ) == E_BLOCK_AIR) // Block attached to was destroyed?
{
m_IsInGround = false; // Yes, begin simulating physics again
}
}
}
示例3: MoveItemsOut
/// 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: 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;
case E_BLOCK_LIT_FURNACE: res = MoveItemsToFurnace(*DestChunk, bx, by, bz, Meta); break;
}
// If the item has been moved, reset the last tick:
if (res)
{
m_LastMoveItemsOutTick = a_CurrentTick;
}
return res;
}
示例4: MoveItemsToChest
/// 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;
}
示例5: MoveItemsFromChest
/// 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;
}
示例6: HandlePhysics
void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk)
{
int PosY = (int)floor(GetPosY());
if ((PosY <= 0) || (PosY >= cChunkDef::Height))
{
// Outside the world, just process normal falling physics
super::HandlePhysics(a_Dt, a_Chunk);
BroadcastMovementUpdate();
return;
}
int RelPosX = (int)floor(GetPosX()) - a_Chunk.GetPosX() * cChunkDef::Width;
int RelPosZ = (int)floor(GetPosZ()) - a_Chunk.GetPosZ() * cChunkDef::Width;
cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelPosX, RelPosZ);
if (Chunk == NULL)
{
// Inside an unloaded chunk, bail out all processing
return;
}
BLOCKTYPE BelowType = Chunk->GetBlock(RelPosX, PosY - 1, RelPosZ);
BLOCKTYPE InsideType = Chunk->GetBlock(RelPosX, PosY, RelPosZ);
if (IsBlockRail(BelowType))
{
HandleRailPhysics(a_Dt, *Chunk);
}
else
{
if (IsBlockRail(InsideType))
{
SetPosY(PosY + 1);
HandleRailPhysics(a_Dt, *Chunk);
}
else
{
super::HandlePhysics(a_Dt, *Chunk);
BroadcastMovementUpdate();
}
}
}
示例7: HandlePhysics
void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk)
{
if (IsDestroyed()) // Mainly to stop detector rails triggering again after minecart is dead
{
return;
}
int PosY = POSY_TOINT;
if ((PosY <= 0) || (PosY >= cChunkDef::Height))
{
// Outside the world, just process normal falling physics
super::HandlePhysics(a_Dt, a_Chunk);
BroadcastMovementUpdate();
return;
}
int RelPosX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width;
int RelPosZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width;
cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelPosX, RelPosZ);
if (Chunk == NULL)
{
// Inside an unloaded chunk, bail out all processing
return;
}
BLOCKTYPE InsideType;
NIBBLETYPE InsideMeta;
Chunk->GetBlockTypeMeta(RelPosX, PosY, RelPosZ, InsideType, InsideMeta);
if (!IsBlockRail(InsideType))
{
Chunk->GetBlockTypeMeta(RelPosX, PosY + 1, RelPosZ, InsideType, InsideMeta); // When an descending minecart hits a flat rail, it goes through the ground; check for this
if (IsBlockRail(InsideType)) AddPosY(1); // Push cart upwards
}
bool WasDetectorRail = false;
if (IsBlockRail(InsideType))
{
if (InsideType == E_BLOCK_RAIL)
{
SnapToRail(InsideMeta);
}
else
{
SnapToRail(InsideMeta & 0x07);
}
switch (InsideType)
{
case E_BLOCK_RAIL:
HandleRailPhysics(InsideMeta, a_Dt);
break;
case E_BLOCK_ACTIVATOR_RAIL:
break;
case E_BLOCK_POWERED_RAIL:
HandlePoweredRailPhysics(InsideMeta);
break;
case E_BLOCK_DETECTOR_RAIL:
{
HandleDetectorRailPhysics(InsideMeta, a_Dt);
WasDetectorRail = true;
break;
}
default:
VERIFY(!"Unhandled rail type despite checking if block was rail!");
break;
}
AddPosition(GetSpeed() * (a_Dt / 1000)); // Commit changes; as we use our own engine when on rails, this needs to be done, whereas it is normally in Entity.cpp
}
else
{
// Not on rail, default physics
SetPosY(floor(GetPosY()) + 0.35); // HandlePhysics overrides this if minecart can fall, else, it is to stop ground clipping minecart bottom when off-rail
super::HandlePhysics(a_Dt, *Chunk);
}
if (m_bIsOnDetectorRail && !Vector3i(POSX_TOINT, POSY_TOINT, POSZ_TOINT).Equals(m_DetectorRailPosition))
{
m_World->SetBlock(m_DetectorRailPosition.x, m_DetectorRailPosition.y, m_DetectorRailPosition.z, E_BLOCK_DETECTOR_RAIL, m_World->GetBlockMeta(m_DetectorRailPosition) & 0x07);
m_bIsOnDetectorRail = false;
}
else if (WasDetectorRail)
{
m_bIsOnDetectorRail = true;
m_DetectorRailPosition = Vector3i(POSX_TOINT, POSY_TOINT, POSZ_TOINT);
}
// Broadcast positioning changes to client
BroadcastMovementUpdate();
}
示例8: DropSpenseFromSlot
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);
int BlockX = (DispX + DispChunk->GetPosX() * cChunkDef::Width);
int BlockZ = (DispZ + DispChunk->GetPosZ() * cChunkDef::Width);
// 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, 80, 0); // 80 ticks fuse, no initial velocity
//.........这里部分代码省略.........
示例9: MoveItemsToChest
/// 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;
}
示例10: MoveItemsFromChest
/// 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;
}
示例11: MoveItemsOut
/// 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;
}
// Get the coords of the block where to output items:
int OutX, OutY, OutZ;
NIBBLETYPE Meta = a_Chunk.GetMeta(m_RelX, m_PosY, m_RelZ);
if (!GetOutputBlockPos(Meta, OutX, OutY, OutZ))
{
// Not attached to another container
return false;
}
if (OutY < 0)
{
// Cannot output below the zero-th block level
return false;
}
// Convert coords to relative:
int OutRelX = OutX - a_Chunk.GetPosX() * cChunkDef::Width;
int OutRelZ = OutZ - a_Chunk.GetPosZ() * cChunkDef::Width;
cChunk * DestChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(OutRelX, OutRelZ);
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(OutRelX, OutY, OutRelZ))
{
case E_BLOCK_TRAPPED_CHEST:
case E_BLOCK_CHEST:
{
// Chests have special handling because of double-chests
res = MoveItemsToChest(*DestChunk, OutX, OutY, OutZ);
break;
}
case E_BLOCK_LIT_FURNACE:
case E_BLOCK_FURNACE:
{
// Furnaces have special handling because of the direction-to-slot relation
res = MoveItemsToFurnace(*DestChunk, OutX, OutY, OutZ, Meta);
break;
}
case E_BLOCK_DISPENSER:
case E_BLOCK_DROPPER:
case E_BLOCK_HOPPER:
{
cBlockEntityWithItems * BlockEntity = (cBlockEntityWithItems *)DestChunk->GetBlockEntity(OutX, OutY, OutZ);
if (BlockEntity == NULL)
{
LOGWARNING("%s: A block entity was not found where expected at {%d, %d, %d}", __FUNCTION__, OutX, OutY, OutZ);
return false;
}
res = MoveItemsToGrid(*BlockEntity);
break;
}
}
// If the item has been moved, reset the last tick:
if (res)
{
m_LastMoveItemsOutTick = a_CurrentTick;
}
return res;
}
示例12: DropSpenseFromSlot
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, 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;
//.........这里部分代码省略.........
示例13: TickBurning
void cEntity::TickBurning(cChunk & a_Chunk)
{
// Remember the current burning state:
bool HasBeenBurning = (m_TicksLeftBurning > 0);
// Do the burning damage:
if (m_TicksLeftBurning > 0)
{
m_TicksSinceLastBurnDamage++;
if (m_TicksSinceLastBurnDamage >= BURN_TICKS_PER_DAMAGE)
{
TakeDamage(dtOnFire, NULL, BURN_DAMAGE, 0);
m_TicksSinceLastBurnDamage = 0;
}
m_TicksLeftBurning--;
}
// Update the burning times, based on surroundings:
int MinRelX = (int)floor(GetPosX() - m_Width / 2) - a_Chunk.GetPosX() * cChunkDef::Width;
int MaxRelX = (int)floor(GetPosX() + m_Width / 2) - a_Chunk.GetPosX() * cChunkDef::Width;
int MinRelZ = (int)floor(GetPosZ() - m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width;
int MaxRelZ = (int)floor(GetPosZ() + m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width;
int MinY = std::max(0, std::min(cChunkDef::Height - 1, (int)floor(GetPosY())));
int MaxY = std::max(0, std::min(cChunkDef::Height - 1, (int)ceil (GetPosY() + m_Height)));
bool HasWater = false;
bool HasLava = false;
bool HasFire = false;
for (int x = MinRelX; x <= MaxRelX; x++)
{
for (int z = MinRelZ; z <= MaxRelZ; z++)
{
int RelX = x;
int RelZ = z;
cChunk * CurChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelX, RelZ);
if (CurChunk == NULL)
{
continue;
}
for (int y = MinY; y <= MaxY; y++)
{
switch (CurChunk->GetBlock(RelX, y, RelZ))
{
case E_BLOCK_FIRE:
{
HasFire = true;
break;
}
case E_BLOCK_LAVA:
case E_BLOCK_STATIONARY_LAVA:
{
HasLava = true;
break;
}
case E_BLOCK_STATIONARY_WATER:
case E_BLOCK_WATER:
{
HasWater = true;
break;
}
} // switch (BlockType)
} // for y
} // for z
} // for x
if (HasWater)
{
// Extinguish the fire
m_TicksLeftBurning = 0;
}
if (HasLava)
{
// Burn:
m_TicksLeftBurning = BURN_TICKS;
// Periodically damage:
m_TicksSinceLastLavaDamage++;
if (m_TicksSinceLastLavaDamage >= LAVA_TICKS_PER_DAMAGE)
{
TakeDamage(dtLavaContact, NULL, LAVA_DAMAGE, 0);
m_TicksSinceLastLavaDamage = 0;
}
}
else
{
m_TicksSinceLastLavaDamage = 0;
}
if (HasFire)
{
// Burn:
m_TicksLeftBurning = BURN_TICKS;
// Periodically damage:
m_TicksSinceLastFireDamage++;
if (m_TicksSinceLastFireDamage >= FIRE_TICKS_PER_DAMAGE)
{
TakeDamage(dtFireContact, NULL, FIRE_DAMAGE, 0);
m_TicksSinceLastFireDamage = 0;
//.........这里部分代码省略.........