aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.World/PistonBaseTile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Minecraft.World/PistonBaseTile.cpp')
-rw-r--r--Minecraft.World/PistonBaseTile.cpp583
1 files changed, 308 insertions, 275 deletions
diff --git a/Minecraft.World/PistonBaseTile.cpp b/Minecraft.World/PistonBaseTile.cpp
index cbad5cec..c71bbf95 100644
--- a/Minecraft.World/PistonBaseTile.cpp
+++ b/Minecraft.World/PistonBaseTile.cpp
@@ -41,9 +41,9 @@ PistonBaseTile::PistonBaseTile(int id, bool isSticky) : Tile(id, Material::pisto
// 4J - added initialiser
ignoreUpdate(false);
- this->isSticky = isSticky;
- setSoundType(SOUND_STONE);
- setDestroyTime(0.5f);
+ this->isSticky = isSticky;
+ setSoundType(SOUND_STONE);
+ setDestroyTime(0.5f);
iconInside = NULL;
iconBack = NULL;
@@ -52,7 +52,7 @@ PistonBaseTile::PistonBaseTile(int id, bool isSticky) : Tile(id, Material::pisto
Icon *PistonBaseTile::getPlatformTexture()
{
- return iconPlatform;
+ return iconPlatform;
}
void PistonBaseTile::updateShape(float x0, float y0, float z0, float x1, float y1, float z1)
@@ -62,32 +62,32 @@ void PistonBaseTile::updateShape(float x0, float y0, float z0, float x1, float y
Icon *PistonBaseTile::getTexture(int face, int data)
{
- int facing = getFacing(data);
+ int facing = getFacing(data);
- if (facing > 5)
+ if (facing > 5)
{
- return iconPlatform;
- }
+ return iconPlatform;
+ }
- if (face == facing)
+ if (face == facing)
{
- // sorry about this mess...
- // when the piston is extended, either normally
- // or because a piston arm animation, the top
- // texture is the furnace bottom
+ // sorry about this mess...
+ // when the piston is extended, either normally
+ // or because a piston arm animation, the top
+ // texture is the furnace bottom
ThreadStorage *tls = (ThreadStorage *)TlsGetValue(Tile::tlsIdxShape);
- if (isExtended(data) || tls->xx0 > 0 || tls->yy0 > 0 || tls->zz0 > 0 || tls->xx1 < 1 || tls->yy1 < 1 || tls->zz1 < 1)
+ if (isExtended(data) || tls->xx0 > 0 || tls->yy0 > 0 || tls->zz0 > 0 || tls->xx1 < 1 || tls->yy1 < 1 || tls->zz1 < 1)
{
- return iconInside;
- }
- return iconPlatform;
- }
- if (face == Facing::OPPOSITE_FACING[facing])
+ return iconInside;
+ }
+ return iconPlatform;
+ }
+ if (face == Facing::OPPOSITE_FACING[facing])
{
- return iconBack;
- }
+ return iconBack;
+ }
- return icon;
+ return icon;
}
Icon *PistonBaseTile::getTexture(const wstring &name)
@@ -124,107 +124,112 @@ bool PistonBaseTile::use(Level *level, int x, int y, int z, shared_ptr<Player> p
return false;
}
-void PistonBaseTile::setPlacedBy(Level *level, int x, int y, int z, shared_ptr<Mob> by)
+void PistonBaseTile::setPlacedBy(Level *level, int x, int y, int z, shared_ptr<LivingEntity> by, shared_ptr<ItemInstance> itemInstance)
{
- int targetData = getNewFacing(level, x, y, z, dynamic_pointer_cast<Player>(by) );
- level->setData(x, y, z, targetData);
- if (!level->isClientSide && !ignoreUpdate())
+ int targetData = getNewFacing(level, x, y, z, dynamic_pointer_cast<Player>(by) );
+ level->setData(x, y, z, targetData, Tile::UPDATE_CLIENTS);
+ if (!level->isClientSide && !ignoreUpdate())
{
- checkIfExtend(level, x, y, z);
- }
+ checkIfExtend(level, x, y, z);
+ }
}
void PistonBaseTile::neighborChanged(Level *level, int x, int y, int z, int type)
{
- if (!level->isClientSide && !ignoreUpdate())
+ if (!level->isClientSide && !ignoreUpdate())
{
- checkIfExtend(level, x, y, z);
- }
+ checkIfExtend(level, x, y, z);
+ }
}
void PistonBaseTile::onPlace(Level *level, int x, int y, int z)
{
- if (!level->isClientSide && level->getTileEntity(x, y, z) == NULL && !ignoreUpdate())
+ if (!level->isClientSide && level->getTileEntity(x, y, z) == NULL && !ignoreUpdate())
{
- checkIfExtend(level, x, y, z);
- }
+ checkIfExtend(level, x, y, z);
+ }
}
void PistonBaseTile::checkIfExtend(Level *level, int x, int y, int z)
{
- int data = level->getData(x, y, z);
- int facing = getFacing(data);
+ int data = level->getData(x, y, z);
+ int facing = getFacing(data);
- if (facing == UNDEFINED_FACING)
+ if (facing == UNDEFINED_FACING)
{
- return;
- }
- bool extend = getNeighborSignal(level, x, y, z, facing);
+ return;
+ }
+ bool extend = getNeighborSignal(level, x, y, z, facing);
- if (extend && !isExtended(data))
+ if (extend && !isExtended(data))
{
- if (canPush(level, x, y, z, facing))
+ if (canPush(level, x, y, z, facing))
{
- //level->setDataNoUpdate(x, y, z, facing | EXTENDED_BIT);
- level->tileEvent(x, y, z, id, TRIGGER_EXTEND, facing);
- }
- }
+ level->tileEvent(x, y, z, id, TRIGGER_EXTEND, facing);
+ }
+ }
else if (!extend && isExtended(data))
{
- //level->setDataNoUpdate(x, y, z, facing);
- level->tileEvent(x, y, z, id, TRIGGER_CONTRACT, facing);
- }
+ level->setData(x, y, z, facing, UPDATE_CLIENTS);
+ level->tileEvent(x, y, z, id, TRIGGER_CONTRACT, facing);
+ }
}
/**
- * This method checks neighbor signals for this block and the block above,
- * and directly beneath. However, it avoids checking blocks that would be
- * pushed by this block.
- *
- * @param level
- * @param x
- * @param y
- * @param z
- * @return
- */
+* This method checks neighbor signals for this block and the block above,
+* and directly beneath. However, it avoids checking blocks that would be
+* pushed by this block.
+*
+* @param level
+* @param x
+* @param y
+* @param z
+* @return
+*/
bool PistonBaseTile::getNeighborSignal(Level *level, int x, int y, int z, int facing)
{
- // check adjacent neighbors, but not in push direction
- if (facing != Facing::DOWN && level->getSignal(x, y - 1, z, Facing::DOWN)) return true;
- if (facing != Facing::UP && level->getSignal(x, y + 1, z, Facing::UP)) return true;
- if (facing != Facing::NORTH && level->getSignal(x, y, z - 1, Facing::NORTH)) return true;
- if (facing != Facing::SOUTH && level->getSignal(x, y, z + 1, Facing::SOUTH)) return true;
- if (facing != Facing::EAST && level->getSignal(x + 1, y, z, Facing::EAST)) return true;
- if (facing != Facing::WEST && level->getSignal(x - 1, y, z, Facing::WEST)) return true;
-
- // check signals above
- if (level->getSignal(x, y, z, 0)) return true;
- if (level->getSignal(x, y + 2, z, 1)) return true;
- if (level->getSignal(x, y + 1, z - 1, 2)) return true;
- if (level->getSignal(x, y + 1, z + 1, 3)) return true;
- if (level->getSignal(x - 1, y + 1, z, 4)) return true;
- if (level->getSignal(x + 1, y + 1, z, 5)) return true;
-
- return false;
+ // check adjacent neighbors, but not in push direction
+ if (facing != Facing::DOWN && level->hasSignal(x, y - 1, z, Facing::DOWN)) return true;
+ if (facing != Facing::UP && level->hasSignal(x, y + 1, z, Facing::UP)) return true;
+ if (facing != Facing::NORTH && level->hasSignal(x, y, z - 1, Facing::NORTH)) return true;
+ if (facing != Facing::SOUTH && level->hasSignal(x, y, z + 1, Facing::SOUTH)) return true;
+ if (facing != Facing::EAST && level->hasSignal(x + 1, y, z, Facing::EAST)) return true;
+ if (facing != Facing::WEST && level->hasSignal(x - 1, y, z, Facing::WEST)) return true;
+
+ // check signals above
+ if (level->hasSignal(x, y, z, 0)) return true;
+ if (level->hasSignal(x, y + 2, z, 1)) return true;
+ if (level->hasSignal(x, y + 1, z - 1, 2)) return true;
+ if (level->hasSignal(x, y + 1, z + 1, 3)) return true;
+ if (level->hasSignal(x - 1, y + 1, z, 4)) return true;
+ if (level->hasSignal(x + 1, y + 1, z, 5)) return true;
+
+ return false;
}
-void PistonBaseTile::triggerEvent(Level *level, int x, int y, int z, int param1, int facing)
+bool PistonBaseTile::triggerEvent(Level *level, int x, int y, int z, int param1, int facing)
{
ignoreUpdate(true);
- if (param1 == TRIGGER_EXTEND)
- {
- level->setDataNoUpdate(x, y, z, facing | EXTENDED_BIT);
- }
- else
+ if (!level->isClientSide)
{
- level->setDataNoUpdate(x, y, z, facing);
+ bool extend = getNeighborSignal(level, x, y, z, facing);
+
+ if (extend && param1 == TRIGGER_CONTRACT)
+ {
+ level->setData(x, y, z, facing | EXTENDED_BIT, UPDATE_CLIENTS);
+ return false;
+ }
+ else if (!extend && param1 == TRIGGER_EXTEND)
+ {
+ return false;
+ }
}
- if (param1 == TRIGGER_EXTEND)
+ if (param1 == TRIGGER_EXTEND)
{
PIXBeginNamedEvent(0,"Create push\n");
- if (createPush(level, x, y, z, facing))
+ if (createPush(level, x, y, z, facing))
{
// 4J - it is (currently) critical that this setData sends data to the client, so have added a bool to the method so that it sends data even if the data was already set to the same value
// as before, which was actually its behaviour until a change in 1.0.1 meant that setData only conditionally sent updates to listeners. If the data update Isn't sent, then what
@@ -237,139 +242,140 @@ void PistonBaseTile::triggerEvent(Level *level, int x, int y, int z, int param1,
// We really need to spend some time investigating a better way for pistons to work as it all seems a bit scary how the host/client interact, but forcing this to send should at least
// restore the behaviour of the pistons to something closer to what they were before the 1.0.1 update. By sending this data update, then (4) in the list above doesn't happen
// because the client does actually receive an update for this tile from the host after the event has been processed on the cient.
- level->setData(x, y, z, facing | EXTENDED_BIT, true);
- level->playSound(x + 0.5, y + 0.5, z + 0.5, eSoundType_TILE_PISTON_OUT, 0.5f, level->random->nextFloat() * 0.25f + 0.6f);
- }
+ level->setData(x, y, z, facing | EXTENDED_BIT, Tile::UPDATE_CLIENTS, true);
+ level->playSound(x + 0.5, y + 0.5, z + 0.5, eSoundType_TILE_PISTON_OUT, 0.5f, level->random->nextFloat() * 0.25f + 0.6f);
+ }
else
{
- level->setDataNoUpdate(x, y, z, facing);
+ return false;
}
PIXEndNamedEvent();
- }
+ }
else if (param1 == TRIGGER_CONTRACT)
{
PIXBeginNamedEvent(0,"Contract phase A\n");
- shared_ptr<TileEntity> prevTileEntity = level->getTileEntity(x + Facing::STEP_X[facing], y + Facing::STEP_Y[facing], z + Facing::STEP_Z[facing]);
- if (prevTileEntity != NULL && dynamic_pointer_cast<PistonPieceEntity>(prevTileEntity) != NULL)
+ shared_ptr<TileEntity> prevTileEntity = level->getTileEntity(x + Facing::STEP_X[facing], y + Facing::STEP_Y[facing], z + Facing::STEP_Z[facing]);
+ if (prevTileEntity != NULL && dynamic_pointer_cast<PistonPieceEntity>(prevTileEntity) != NULL)
{
- dynamic_pointer_cast<PistonPieceEntity>(prevTileEntity)->finalTick();
- }
+ dynamic_pointer_cast<PistonPieceEntity>(prevTileEntity)->finalTick();
+ }
stopSharingIfServer(level, x, y, z); // 4J added
- level->setTileAndDataNoUpdate(x, y, z, Tile::pistonMovingPiece_Id, facing);
- level->setTileEntity(x, y, z, PistonMovingPiece::newMovingPieceEntity(id, facing, facing, false, true));
+ level->setTileAndData(x, y, z, Tile::pistonMovingPiece_Id, facing, Tile::UPDATE_ALL);
+ level->setTileEntity(x, y, z, PistonMovingPiece::newMovingPieceEntity(id, facing, facing, false, true));
PIXEndNamedEvent();
- // sticky movement
- if (isSticky)
+ // sticky movement
+ if (isSticky)
{
PIXBeginNamedEvent(0,"Contract sticky phase A\n");
- int twoX = x + Facing::STEP_X[facing] * 2;
- int twoY = y + Facing::STEP_Y[facing] * 2;
- int twoZ = z + Facing::STEP_Z[facing] * 2;
- int block = level->getTile(twoX, twoY, twoZ);
- int blockData = level->getData(twoX, twoY, twoZ);
- bool pistonPiece = false;
+ int twoX = x + Facing::STEP_X[facing] * 2;
+ int twoY = y + Facing::STEP_Y[facing] * 2;
+ int twoZ = z + Facing::STEP_Z[facing] * 2;
+ int block = level->getTile(twoX, twoY, twoZ);
+ int blockData = level->getData(twoX, twoY, twoZ);
+ bool pistonPiece = false;
PIXEndNamedEvent();
- if (block == Tile::pistonMovingPiece_Id)
+ if (block == Tile::pistonMovingPiece_Id)
{
PIXBeginNamedEvent(0,"Contract sticky phase B\n");
- // the block two steps away is a moving piston block piece,
- // so replace it with the real data, since it's probably
- // this piston which is changing too fast
- shared_ptr<TileEntity> tileEntity = level->getTileEntity(twoX, twoY, twoZ);
- if (tileEntity != NULL && dynamic_pointer_cast<PistonPieceEntity>(tileEntity) != NULL )
+ // the block two steps away is a moving piston block piece, so replace it with the real data,
+ // since it's probably this piston which is changing too fast
+ shared_ptr<TileEntity> tileEntity = level->getTileEntity(twoX, twoY, twoZ);
+ if (tileEntity != NULL && dynamic_pointer_cast<PistonPieceEntity>(tileEntity) != NULL )
{
- shared_ptr<PistonPieceEntity> ppe = dynamic_pointer_cast<PistonPieceEntity>(tileEntity);
+ shared_ptr<PistonPieceEntity> ppe = dynamic_pointer_cast<PistonPieceEntity>(tileEntity);
- if (ppe->getFacing() == facing && ppe->isExtending())
+ if (ppe->getFacing() == facing && ppe->isExtending())
{
- // force the tile to air before pushing
- ppe->finalTick();
- block = ppe->getId();
- blockData = ppe->getData();
- pistonPiece = true;
- }
- }
+ // force the tile to air before pushing
+ ppe->finalTick();
+ block = ppe->getId();
+ blockData = ppe->getData();
+ pistonPiece = true;
+ }
+ }
PIXEndNamedEvent();
- }
+ }
PIXBeginNamedEvent(0,"Contract sticky phase C\n");
- if (!pistonPiece && block > 0 && (isPushable(block, level, twoX, twoY, twoZ, false))
- && (Tile::tiles[block]->getPistonPushReaction() == Material::PUSH_NORMAL || block == Tile::pistonBase_Id || block == Tile::pistonStickyBase_Id))
+ if (!pistonPiece && block > 0 && (isPushable(block, level, twoX, twoY, twoZ, false))
+ && (Tile::tiles[block]->getPistonPushReaction() == Material::PUSH_NORMAL || block == Tile::pistonBase_Id || block == Tile::pistonStickyBase_Id))
{
stopSharingIfServer(level, twoX, twoY, twoZ); // 4J added
- x += Facing::STEP_X[facing];
- y += Facing::STEP_Y[facing];
- z += Facing::STEP_Z[facing];
+ x += Facing::STEP_X[facing];
+ y += Facing::STEP_Y[facing];
+ z += Facing::STEP_Z[facing];
- level->setTileAndDataNoUpdate(x, y, z, Tile::pistonMovingPiece_Id, blockData);
- level->setTileEntity(x, y, z, PistonMovingPiece::newMovingPieceEntity(block, blockData, facing, false, false));
+ level->setTileAndData(x, y, z, Tile::pistonMovingPiece_Id, blockData, Tile::UPDATE_ALL);
+ level->setTileEntity(x, y, z, PistonMovingPiece::newMovingPieceEntity(block, blockData, facing, false, false));
ignoreUpdate(false);
- level->setTile(twoX, twoY, twoZ, 0);
+ level->removeTile(twoX, twoY, twoZ);
ignoreUpdate(true);
}
else if (!pistonPiece)
{
stopSharingIfServer(level, x + Facing::STEP_X[facing], y + Facing::STEP_Y[facing], z + Facing::STEP_Z[facing]); // 4J added
ignoreUpdate(false);
- level->setTile(x + Facing::STEP_X[facing], y + Facing::STEP_Y[facing], z + Facing::STEP_Z[facing], 0);
+ level->removeTile(x + Facing::STEP_X[facing], y + Facing::STEP_Y[facing], z + Facing::STEP_Z[facing]);
ignoreUpdate(true);
- }
+ }
PIXEndNamedEvent();
- }
+ }
else
{
stopSharingIfServer(level, x + Facing::STEP_X[facing], y + Facing::STEP_Y[facing], z + Facing::STEP_Z[facing]); // 4J added
ignoreUpdate(false);
- level->setTile(x + Facing::STEP_X[facing], y + Facing::STEP_Y[facing], z + Facing::STEP_Z[facing], 0);
+ level->removeTile(x + Facing::STEP_X[facing], y + Facing::STEP_Y[facing], z + Facing::STEP_Z[facing]);
ignoreUpdate(true);
- }
+ }
- level->playSound(x + 0.5, y + 0.5, z + 0.5, eSoundType_TILE_PISTON_IN, 0.5f, level->random->nextFloat() * 0.15f + 0.6f);
- }
+ level->playSound(x + 0.5, y + 0.5, z + 0.5, eSoundType_TILE_PISTON_IN, 0.5f, level->random->nextFloat() * 0.15f + 0.6f);
+ }
ignoreUpdate(false);
+
+ return true;
}
void PistonBaseTile::updateShape(LevelSource *level, int x, int y, int z, int forceData, shared_ptr<TileEntity> forceEntity) // 4J added forceData, forceEntity param
{
- int data = (forceData == -1 ) ? level->getData(x, y, z) : forceData;
+ int data = (forceData == -1 ) ? level->getData(x, y, z) : forceData;
- if (isExtended(data))
+ if (isExtended(data))
{
- const float thickness = PLATFORM_THICKNESS / 16.0f;
- switch (getFacing(data))
+ const float thickness = PLATFORM_THICKNESS / 16.0f;
+ switch (getFacing(data))
{
case Facing::DOWN:
- setShape(0, thickness, 0, 1, 1, 1);
- break;
+ setShape(0, thickness, 0, 1, 1, 1);
+ break;
case Facing::UP:
- setShape(0, 0, 0, 1, 1 - thickness, 1);
- break;
+ setShape(0, 0, 0, 1, 1 - thickness, 1);
+ break;
case Facing::NORTH:
- setShape(0, 0, thickness, 1, 1, 1);
- break;
+ setShape(0, 0, thickness, 1, 1, 1);
+ break;
case Facing::SOUTH:
- setShape(0, 0, 0, 1, 1, 1 - thickness);
- break;
+ setShape(0, 0, 0, 1, 1, 1 - thickness);
+ break;
case Facing::WEST:
- setShape(thickness, 0, 0, 1, 1, 1);
- break;
+ setShape(thickness, 0, 0, 1, 1, 1);
+ break;
case Facing::EAST:
- setShape(0, 0, 0, 1 - thickness, 1, 1);
- break;
- }
- }
+ setShape(0, 0, 0, 1 - thickness, 1, 1);
+ break;
+ }
+ }
else
{
- setShape(0, 0, 0, 1, 1, 1);
- }
+ setShape(0, 0, 0, 1, 1, 1);
+ }
}
void PistonBaseTile::updateDefaultShape()
@@ -379,8 +385,8 @@ void PistonBaseTile::updateDefaultShape()
void PistonBaseTile::addAABBs(Level *level, int x, int y, int z, AABB *box, AABBList *boxes, shared_ptr<Entity> source)
{
- setShape(0, 0, 0, 1, 1, 1);
- Tile::addAABBs(level, x, y, z, box, boxes, source);
+ setShape(0, 0, 0, 1, 1, 1);
+ Tile::addAABBs(level, x, y, z, box, boxes, source);
}
AABB *PistonBaseTile::getAABB(Level *level, int x, int y, int z)
@@ -404,64 +410,68 @@ bool PistonBaseTile::isExtended(int data)
return (data & EXTENDED_BIT) != 0;
}
-int PistonBaseTile::getNewFacing(Level *level, int x, int y, int z, shared_ptr<Player> player)
+int PistonBaseTile::getNewFacing(Level *level, int x, int y, int z, shared_ptr<LivingEntity> player)
{
- if (Mth::abs((float) player->x - x) < 2 && Mth::abs((float) player->z - z) < 2)
+ if (Mth::abs((float) player->x - x) < 2 && Mth::abs((float) player->z - z) < 2)
{
- // If the player is above the block, the slot is on the top
- double py = player->y + 1.82 - player->heightOffset;
- if (py - y > 2)
+ // If the player is above the block, the slot is on the top
+ double py = player->y + 1.82 - player->heightOffset;
+ if (py - y > 2)
{
- return Facing::UP;
- }
- // If the player is below the block, the slot is on the bottom
- if (y - py > 0)
+ return Facing::UP;
+ }
+ // If the player is below the block, the slot is on the bottom
+ if (y - py > 0)
{
- return Facing::DOWN;
- }
- }
- // The slot is on the side
- int i = Mth::floor(player->yRot * 4.0f / 360.0f + 0.5) & 0x3;
- if (i == 0) return Facing::NORTH;
- if (i == 1) return Facing::EAST;
- if (i == 2) return Facing::SOUTH;
- if (i == 3) return Facing::WEST;
- return 0;
+ return Facing::DOWN;
+ }
+ }
+ // The slot is on the side
+ int i = Mth::floor(player->yRot * 4.0f / 360.0f + 0.5) & 0x3;
+ if (i == 0) return Facing::NORTH;
+ if (i == 1) return Facing::EAST;
+ if (i == 2) return Facing::SOUTH;
+ if (i == 3) return Facing::WEST;
+ return 0;
}
bool PistonBaseTile::isPushable(int block, Level *level, int cx, int cy, int cz, bool allowDestroyable)
{
- // special case for obsidian
- if (block == Tile::obsidian_Id)
+ // special case for obsidian
+ if (block == Tile::obsidian_Id)
{
- return false;
- }
+ return false;
+ }
- if (block == Tile::pistonBase_Id || block == Tile::pistonStickyBase_Id)
+ if (block == Tile::pistonBase_Id || block == Tile::pistonStickyBase_Id)
{
- // special case for piston bases
- if (isExtended(level->getData(cx, cy, cz)))
+ // special case for piston bases
+ if (isExtended(level->getData(cx, cy, cz)))
{
- return false;
- }
- }
+ return false;
+ }
+ }
else
{
- if (Tile::tiles[block]->getDestroySpeed(level, cx, cy, cz) == Tile::INDESTRUCTIBLE_DESTROY_TIME)
+ if (Tile::tiles[block]->getDestroySpeed(level, cx, cy, cz) == Tile::INDESTRUCTIBLE_DESTROY_TIME)
{
- return false;
- }
+ return false;
+ }
- if (Tile::tiles[block]->getPistonPushReaction() == Material::PUSH_BLOCK)
+ if (Tile::tiles[block]->getPistonPushReaction() == Material::PUSH_BLOCK)
{
- return false;
- }
-
- if (!allowDestroyable && Tile::tiles[block]->getPistonPushReaction() == Material::PUSH_DESTROY)
+ return false;
+ }
+
+ if (Tile::tiles[block]->getPistonPushReaction() == Material::PUSH_DESTROY)
{
- return false;
- }
- }
+ if(!allowDestroyable)
+ {
+ return false;
+ }
+ return true;
+ }
+ }
if( Tile::tiles[block]->isEntityTile() ) // 4J - java uses instanceof EntityTile here
{
@@ -474,19 +484,19 @@ bool PistonBaseTile::isPushable(int block, Level *level, int cx, int cy, int cz,
bool PistonBaseTile::canPush(Level *level, int sx, int sy, int sz, int facing)
{
- int cx = sx + Facing::STEP_X[facing];
- int cy = sy + Facing::STEP_Y[facing];
- int cz = sz + Facing::STEP_Z[facing];
+ int cx = sx + Facing::STEP_X[facing];
+ int cy = sy + Facing::STEP_Y[facing];
+ int cz = sz + Facing::STEP_Z[facing];
- for (int i = 0; i < MAX_PUSH_DEPTH + 1; i++)
+ for (int i = 0; i < MAX_PUSH_DEPTH + 1; i++)
{
if (cy <= 0 || cy >= (Level::maxBuildHeight - 1))
{
- // out of bounds
- return false;
- }
-
+ // out of bounds
+ return false;
+ }
+
// 4J - added to also check for out of bounds in x/z for our finite world
int minXZ = - (level->dimension->getXZSize() * 16 ) / 2;
int maxXZ = (level->dimension->getXZSize() * 16 ) / 2 - 1;
@@ -494,35 +504,35 @@ bool PistonBaseTile::canPush(Level *level, int sx, int sy, int sz, int facing)
{
return false;
}
- int block = level->getTile(cx, cy, cz);
- if (block == 0)
+ int block = level->getTile(cx, cy, cz);
+ if (block == 0)
{
- break;
- }
+ break;
+ }
- if (!isPushable(block, level, cx, cy, cz, true))
+ if (!isPushable(block, level, cx, cy, cz, true))
{
- return false;
- }
+ return false;
+ }
- if (Tile::tiles[block]->getPistonPushReaction() == Material::PUSH_DESTROY)
+ if (Tile::tiles[block]->getPistonPushReaction() == Material::PUSH_DESTROY)
{
- break;
- }
+ break;
+ }
- if (i == MAX_PUSH_DEPTH)
+ if (i == MAX_PUSH_DEPTH)
{
- // we've reached the maximum push depth
- // without finding air or a breakable block
- return false;
- }
+ // we've reached the maximum push depth
+ // without finding air or a breakable block
+ return false;
+ }
- cx += Facing::STEP_X[facing];
- cy += Facing::STEP_Y[facing];
- cz += Facing::STEP_Z[facing];
- }
+ cx += Facing::STEP_X[facing];
+ cy += Facing::STEP_Y[facing];
+ cz += Facing::STEP_Z[facing];
+ }
- return true;
+ return true;
}
@@ -541,18 +551,18 @@ void PistonBaseTile::stopSharingIfServer(Level *level, int x, int y, int z)
bool PistonBaseTile::createPush(Level *level, int sx, int sy, int sz, int facing)
{
- int cx = sx + Facing::STEP_X[facing];
- int cy = sy + Facing::STEP_Y[facing];
- int cz = sz + Facing::STEP_Z[facing];
+ int cx = sx + Facing::STEP_X[facing];
+ int cy = sy + Facing::STEP_Y[facing];
+ int cz = sz + Facing::STEP_Z[facing];
- for (int i = 0; i < MAX_PUSH_DEPTH + 1; i++)
+ for (int i = 0; i < MAX_PUSH_DEPTH + 1; i++)
{
if (cy <= 0 || cy >= (Level::maxBuildHeight - 1))
{
- // out of bounds
- return false;
- }
-
+ // out of bounds
+ return false;
+ }
+
// 4J - added to also check for out of bounds in x/z for our finite world
int minXZ = - (level->dimension->getXZSize() * 16 ) / 2;
int maxXZ = (level->dimension->getXZSize() * 16 ) / 2 - 1;
@@ -561,68 +571,91 @@ bool PistonBaseTile::createPush(Level *level, int sx, int sy, int sz, int facing
return false;
}
- int block = level->getTile(cx, cy, cz);
- if (block == 0)
+ int block = level->getTile(cx, cy, cz);
+ if (block == 0)
{
- break;
- }
+ break;
+ }
- if (!isPushable(block, level, cx, cy, cz, true))
+ if (!isPushable(block, level, cx, cy, cz, true))
{
- return false;
- }
+ return false;
+ }
- if (Tile::tiles[block]->getPistonPushReaction() == Material::PUSH_DESTROY)
+ if (Tile::tiles[block]->getPistonPushReaction() == Material::PUSH_DESTROY)
{
- // this block is destroyed when pushed
- Tile::tiles[block]->spawnResources(level, cx, cy, cz, level->getData(cx, cy, cz), 0);
- // setting the tile to air is actually superflous, but
- // helps vs multiplayer problems
+ // this block is destroyed when pushed
+ Tile::tiles[block]->spawnResources(level, cx, cy, cz, level->getData(cx, cy, cz), 0);
+ // setting the tile to air is actually superflous, but helps vs multiplayer problems
stopSharingIfServer(level, cx, cy, cz); // 4J added
- level->setTile(cx, cy, cz, 0);
- break;
- }
+ level->removeTile(cx, cy, cz);
+ break;
+ }
- if (i == MAX_PUSH_DEPTH)
+ if (i == MAX_PUSH_DEPTH)
{
- // we've reached the maximum push depth
- // without finding air or a breakable block
- return false;
- }
+ // we've reached the maximum push depth without finding air or a breakable block
+ return false;
+ }
+
+ cx += Facing::STEP_X[facing];
+ cy += Facing::STEP_Y[facing];
+ cz += Facing::STEP_Z[facing];
+ }
- cx += Facing::STEP_X[facing];
- cy += Facing::STEP_Y[facing];
- cz += Facing::STEP_Z[facing];
- }
+ int ex = cx;
+ int ey = cy;
+ int ez = cz;
+ int count = 0;
+ int tiles[MAX_PUSH_DEPTH + 1];
- while (cx != sx || cy != sy || cz != sz)
+ while (cx != sx || cy != sy || cz != sz)
{
- int nx = cx - Facing::STEP_X[facing];
- int ny = cy - Facing::STEP_Y[facing];
- int nz = cz - Facing::STEP_Z[facing];
+ int nx = cx - Facing::STEP_X[facing];
+ int ny = cy - Facing::STEP_Y[facing];
+ int nz = cz - Facing::STEP_Z[facing];
- int block = level->getTile(nx, ny, nz);
- int data = level->getData(nx, ny, nz);
+ int block = level->getTile(nx, ny, nz);
+ int data = level->getData(nx, ny, nz);
stopSharingIfServer(level, cx, cy, cz); // 4J added
- if (block == id && nx == sx && ny == sy && nz == sz)
+ if (block == id && nx == sx && ny == sy && nz == sz)
{
- level->setTileAndDataNoUpdate(cx, cy, cz, Tile::pistonMovingPiece_Id, facing | (isSticky ? PistonExtensionTile::STICKY_BIT : 0), false);
- level->setTileEntity(cx, cy, cz, PistonMovingPiece::newMovingPieceEntity(Tile::pistonExtensionPiece_Id, facing | (isSticky ? PistonExtensionTile::STICKY_BIT : 0), facing, true, false));
- }
+ level->setTileAndData(cx, cy, cz, Tile::pistonMovingPiece_Id, facing | (isSticky ? PistonExtensionTile::STICKY_BIT : 0), Tile::UPDATE_NONE);
+ level->setTileEntity(cx, cy, cz, PistonMovingPiece::newMovingPieceEntity(Tile::pistonExtensionPiece_Id, facing | (isSticky ? PistonExtensionTile::STICKY_BIT : 0), facing, true, false));
+ }
else
{
- level->setTileAndDataNoUpdate(cx, cy, cz, Tile::pistonMovingPiece_Id, data, false);
- level->setTileEntity(cx, cy, cz, PistonMovingPiece::newMovingPieceEntity(block, data, facing, true, false));
- }
+ level->setTileAndData(cx, cy, cz, Tile::pistonMovingPiece_Id, data, Tile::UPDATE_NONE);
+ level->setTileEntity(cx, cy, cz, PistonMovingPiece::newMovingPieceEntity(block, data, facing, true, false));
+ }
+ tiles[count++] = block;
- cx = nx;
- cy = ny;
- cz = nz;
- }
+ cx = nx;
+ cy = ny;
+ cz = nz;
+ }
+
+ cx = ex;
+ cy = ey;
+ cz = ez;
+ count = 0;
- return true;
+ while (cx != sx || cy != sy || cz != sz)
+ {
+ int nx = cx - Facing::STEP_X[facing];
+ int ny = cy - Facing::STEP_Y[facing];
+ int nz = cz - Facing::STEP_Z[facing];
+
+ level->updateNeighborsAt(nx, ny, nz, tiles[count++]);
+
+ cx = nx;
+ cy = ny;
+ cz = nz;
+ }
+
+ return true;
}