Ejemplo n.º 1
0
void Choice::Draw(UIContext &dc) {
	if (!IsSticky()) {
		ClickableItem::Draw(dc);
	} else {
		Style style =	dc.theme->itemStyle;
		if (down_) {
			style = dc.theme->itemDownStyle;
		}
		if (HasFocus()) {
			style = dc.theme->itemFocusedStyle;
		}
		dc.FillRect(style.background, bounds_);
	}

	Style style = dc.theme->itemStyle;
	if (!IsEnabled())
		style = dc.theme->itemDisabledStyle;

	if (atlasImage_ != -1) {
		dc.Draw()->DrawImage(atlasImage_, bounds_.centerX(), bounds_.centerY(), 1.0f, style.fgColor, ALIGN_CENTER);
	} else {
		int paddingX = 12;
		dc.SetFontStyle(dc.theme->uiFont);
		dc.DrawText(text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER);
	}

	if (selected_) {
		dc.Draw()->DrawImage(dc.theme->checkOn, bounds_.x2() - 40, bounds_.centerY(), 1.0f, style.fgColor, ALIGN_CENTER);
	}
}
Ejemplo n.º 2
0
void cBlockPistonHandler::ExtendPiston(int pistx, int pisty, int pistz)
{
	BLOCKTYPE pistonBlock;
	NIBBLETYPE pistonMeta;
	m_World->GetBlockTypeMeta(pistx, pisty, pistz, pistonBlock, pistonMeta);
	
	if (IsExtended(pistonMeta))
	{
		// Already extended, bail out
		return;
	}

	int dist = FirstPassthroughBlock(pistx, pisty, pistz, pistonMeta);
	if (dist < 0)
	{
		// FirstPassthroughBlock says piston can't push anything, bail out
		return;
	}

	m_World->BroadcastBlockAction(pistx, pisty, pistz, 0, pistonMeta, pistonBlock);
	m_World->BroadcastSoundEffect("tile.piston.out", pistx * 8, pisty * 8, pistz * 8, 0.5f, 0.7f);	
	
	// Drop the breakable block in the line, if appropriate:
	AddPistonDir(pistx, pisty, pistz, pistonMeta, dist + 1);  // "pist" now at the breakable / empty block
	BLOCKTYPE currBlock;
	NIBBLETYPE currMeta;
	m_World->GetBlockTypeMeta(pistx, pisty, pistz, currBlock, currMeta);
	if (currBlock != E_BLOCK_AIR)
	{
		cBlockHandler * Handler = BlockHandler(currBlock);
		if (Handler->DoesDropOnUnsuitable())
		{
			cChunkInterface ChunkInterface(m_World->GetChunkMap());
			cBlockInServerPluginInterface PluginInterface(*m_World);
			Handler->DropBlock(ChunkInterface, *m_World, PluginInterface, NULL, pistx, pisty, pistz);
		}
	}
	
	// Push blocks, from the furthest to the nearest:
	int oldx = pistx, oldy = pisty, oldz = pistz;
	NIBBLETYPE currBlockMeta;
	for (int i = dist + 1; i > 1; i--)
	{
		AddPistonDir(pistx, pisty, pistz, pistonMeta, -1);
		m_World->GetBlockTypeMeta(pistx, pisty, pistz, currBlock, currBlockMeta);
		m_World->QueueSetBlock( oldx, oldy, oldz, currBlock, currBlockMeta, PISTON_TICK_DELAY);
		oldx = pistx;
		oldy = pisty;
		oldz = pistz;
	}

	int extx = pistx;
	int exty = pisty;
	int extz = pistz;
	AddPistonDir(pistx, pisty, pistz, pistonMeta, -1);
	// "pist" now at piston body, "ext" at future extension
	
	m_World->SetBlock(pistx, pisty, pistz, pistonBlock, pistonMeta | 0x8);
	m_World->QueueSetBlock(extx, exty, extz, E_BLOCK_PISTON_EXTENSION, pistonMeta | (IsSticky(pistonBlock) ? 8 : 0), PISTON_TICK_DELAY);
}
Ejemplo n.º 3
0
void cBlockPistonHandler::ExtendPiston(Vector3i a_BlockPos, cWorld * a_World)
{
	BLOCKTYPE pistonBlock;
	NIBBLETYPE pistonMeta;
	a_World->GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, pistonBlock, pistonMeta);

	if (IsExtended(pistonMeta))
	{
		// Already extended, bail out
		return;
	}

	Vector3i pushDir = MetadataToOffset(pistonMeta);

	Vector3iSet blocksPushed;
	if (!CanPushBlock(a_BlockPos + pushDir, a_World, true, blocksPushed, pushDir))
	{
		// Can't push anything, bail out
		return;
	}

	a_World->BroadcastBlockAction(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, 0, pistonMeta, pistonBlock);
	a_World->BroadcastSoundEffect("tile.piston.out", a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, 0.5f, 0.7f);

	PushBlocks(blocksPushed, a_World, pushDir);

	// Set the extension and the piston base correctly
	Vector3i extensionPos = a_BlockPos + pushDir;
	a_World->SetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, pistonBlock, pistonMeta | 0x8);
	a_World->SetBlock(
		extensionPos.x, extensionPos.y, extensionPos.z,
		E_BLOCK_PISTON_EXTENSION, pistonMeta | (IsSticky(pistonBlock) ? 8 : 0)
	);
}
Ejemplo n.º 4
0
void cBlockPistonHandler::RetractPiston(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World)
{
	BLOCKTYPE pistonBlock;
	NIBBLETYPE pistonMeta;
	a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, pistonBlock, pistonMeta);

	if (!IsExtended(pistonMeta))
	{
		// Already retracted, bail out
		return;
	}

	// Check the extension:
	AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, 1);
	if (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) != E_BLOCK_PISTON_EXTENSION)
	{
		LOGD("%s: Piston without an extension - still extending, or just in an invalid state?", __FUNCTION__);
		return;
	}

	AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, -1);
	a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, pistonBlock, pistonMeta & ~(8));
	a_World->BroadcastBlockAction(a_BlockX, a_BlockY, a_BlockZ, 1, pistonMeta & ~(8), pistonBlock);
	a_World->BroadcastSoundEffect("tile.piston.in", (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 0.5f, 0.7f);
	AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, 1);

	// Retract the extension, pull block if appropriate
	if (IsSticky(pistonBlock))
	{
		int tempx = a_BlockX, tempy = a_BlockY, tempz = a_BlockZ;
		AddPistonDir(tempx, tempy, tempz, pistonMeta, 1);
		BLOCKTYPE tempBlock;
		NIBBLETYPE tempMeta;
		a_World->GetBlockTypeMeta(tempx, tempy, tempz, tempBlock, tempMeta);
		if (CanPull(tempBlock, tempMeta))
		{
			// Pull the block
			a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, tempBlock, tempMeta, false);
			a_World->SetBlock(tempx, tempy, tempz, E_BLOCK_AIR, 0, false);

			std::vector<Vector3i> ScheduledBlocks;
			ScheduledBlocks.push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ));
			ScheduledBlocks.push_back(Vector3i(tempx, tempy, tempz));
			a_World->ScheduleTask(PISTON_TICK_DELAY + 1, new cWorld::cTaskSendBlockToAllPlayers(ScheduledBlocks));
			return;
		}
	}
	
	// Retract without pulling
	a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0, false);

	std::vector<Vector3i> ScheduledBlocks;
	ScheduledBlocks.push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ));
	a_World->ScheduleTask(PISTON_TICK_DELAY + 1, new cWorld::cTaskSendBlockToAllPlayers(ScheduledBlocks));
}
Ejemplo n.º 5
0
void cPiston::RetractPiston(int pistx, int pisty, int pistz)
{
	BLOCKTYPE pistonBlock;
	NIBBLETYPE pistonMeta;
	m_World->GetBlockTypeMeta(pistx, pisty, pistz, pistonBlock, pistonMeta);

	if (!IsExtended(pistonMeta))
	{
		// Already retracted, bail out
		return;
	}

	// Check the extension:
	AddDir(pistx, pisty, pistz, pistonMeta, 1);
	if (m_World->GetBlock(pistx, pisty, pistz) != E_BLOCK_PISTON_EXTENSION)
	{
		LOGD("%s: Piston without an extension - still extending, or just in an invalid state?", __FUNCTION__);
		return;
	}
	
	AddDir(pistx, pisty, pistz, pistonMeta, -1);
	m_World->SetBlock(pistx, pisty, pistz, pistonBlock, pistonMeta & ~(8));
	m_World->BroadcastBlockAction(pistx, pisty, pistz, 1, pistonMeta & ~(8), pistonBlock);
	m_World->BroadcastSoundEffect("tile.piston.in", pistx * 8, pisty * 8, pistz * 8, 0.5f, 0.7f);
	AddDir(pistx, pisty, pistz, pistonMeta, 1);
	
	// Retract the extension, pull block if appropriate
	if (IsSticky(pistonBlock))
	{
		int tempx = pistx, tempy = pisty, tempz = pistz;
		AddDir(tempx, tempy, tempz, pistonMeta, 1);
		BLOCKTYPE tempBlock;
		NIBBLETYPE tempMeta;
		m_World->GetBlockTypeMeta(tempx, tempy, tempz, tempBlock, tempMeta);
		if (CanPull(tempBlock, tempMeta))
		{
			// Pull the block
			m_World->QueueSetBlock(pistx, pisty, pistz, tempBlock, tempMeta, PISTON_TICK_DELAY);
			m_World->QueueSetBlock(tempx, tempy, tempz, E_BLOCK_AIR, 0, PISTON_TICK_DELAY);
		}
		else
		{
			// Retract without pulling
			m_World->QueueSetBlock(pistx, pisty, pistz, E_BLOCK_AIR, 0, PISTON_TICK_DELAY);
		}
	}
	else
	{
		m_World->QueueSetBlock(pistx, pisty, pistz, E_BLOCK_AIR, 0, PISTON_TICK_DELAY);
	}
}
Ejemplo n.º 6
0
    void RegexPattern::Print(DebugWriter* w)
    {
        w->Print(_u("/"));

        Js::InternalString str = GetSource();
        if (str.GetLength() == 0)
            w->Print(_u("(?:)"));
        else
        {
            for (charcount_t i = 0; i < str.GetLength(); ++i)
            {
                const char16 c = str.GetBuffer()[i];
                switch(c)
                {
                case _u('/'):
                    w->Print(_u("\\%lc"), c);
                    break;
                case _u('\n'):
                case _u('\r'):
                case _u('\x2028'):
                case _u('\x2029'):
                    w->PrintEscapedChar(c);
                    break;
                case _u('\\'):
                    Assert(i + 1 < str.GetLength()); // cannot end in a '\'
                    w->Print(_u("\\%lc"), str.GetBuffer()[++i]);
                    break;
                default:
                    w->PrintEscapedChar(c);
                    break;
                }
            }
        }
        w->Print(_u("/"));
        if (IsIgnoreCase())
            w->Print(_u("i"));
        if (IsGlobal())
            w->Print(_u("g"));
        if (IsMultiline())
            w->Print(_u("m"));
        if (IsUnicode())
            w->Print(_u("u"));
        if (IsSticky())
            w->Print(_u("y"));
        w->Print(_u(" /* "));
        w->Print(_u(", "));
        w->Print(isLiteral ? _u("literal") : _u("dynamic"));
        w->Print(_u(" */"));
    }
Ejemplo n.º 7
0
Archivo: view.cpp Proyecto: kg/ppsspp
void Choice::Draw(UIContext &dc) {
	if (!IsSticky()) {
		ClickableItem::Draw(dc);
	} else {
		Style style =	dc.theme->itemStyle;
		if (highlighted_) {
			style = dc.theme->itemHighlightedStyle;
		}
		if (down_) {
			style = dc.theme->itemDownStyle;
		}
		if (HasFocus()) {
			style = dc.theme->itemFocusedStyle;
		}
		dc.FillRect(style.background, bounds_);
	}

	Style style = dc.theme->itemStyle;
	if (!IsEnabled()) {
		style = dc.theme->itemDisabledStyle;
	}

	if (atlasImage_ != -1) {
		dc.Draw()->DrawImage(atlasImage_, bounds_.centerX(), bounds_.centerY(), 1.0f, style.fgColor, ALIGN_CENTER);
	} else {
		dc.SetFontStyle(dc.theme->uiFont);

		const int paddingX = 12;
		const float availWidth = bounds_.w - paddingX * 2 - textPadding_.horiz();
		float scale = CalculateTextScale(dc, availWidth);

		dc.SetFontScale(scale, scale);
		if (centered_) {
			dc.DrawTextRect(text_.c_str(), bounds_, style.fgColor, ALIGN_CENTER | FLAG_WRAP_TEXT);
		} else {
			if (iconImage_ != -1) {
				dc.Draw()->DrawImage(iconImage_, bounds_.x2() - 32 - paddingX, bounds_.centerY(), 0.5f, style.fgColor, ALIGN_CENTER);
			}

			Bounds textBounds(bounds_.x + paddingX + textPadding_.left, bounds_.y, availWidth, bounds_.h);
			dc.DrawTextRect(text_.c_str(), textBounds, style.fgColor, ALIGN_VCENTER | FLAG_WRAP_TEXT);
		}
		dc.SetFontScale(1.0f, 1.0f);
	}

	if (selected_) {
		dc.Draw()->DrawImage(dc.theme->checkOn, bounds_.x2() - 40, bounds_.centerY(), 1.0f, style.fgColor, ALIGN_CENTER);
	}
}
Ejemplo n.º 8
0
    void RegexPattern::Print(DebugWriter* w)
    {
        w->Print(L"/");

        Js::InternalString str = GetSource();
        if (str.GetLength() == 0)
            w->Print(L"(?:)");
        else
        {
            for (charcount_t i = 0; i < str.GetLength(); ++i)
            {
                const wchar_t c = str.GetBuffer()[i];
                switch(c)
                {
                case L'/':
                    w->Print(L"\\%lc", c);
                    break;
                case L'\n':
                case L'\r':
                case L'\x2028':
                case L'\x2029':
                    w->PrintEscapedChar(c);
                    break;
                case L'\\':
                    Assert(i + 1 < str.GetLength()); // cannot end in a '\'
                    w->Print(L"\\%lc", str.GetBuffer()[++i]);
                    break;
                default:
                    w->PrintEscapedChar(c);
                    break;
                }
            }
        }
        w->Print(L"/");
        if (IsIgnoreCase())
            w->Print(L"i");
        if (IsGlobal())
            w->Print(L"g");
        if (IsMultiline())
            w->Print(L"m");
        if (IsUnicode())
            w->Print(L"u");
        if (IsSticky())
            w->Print(L"y");
        w->Print(L" /* ");
        w->Print(L", ");
        w->Print(isLiteral ? L"literal" : L"dynamic");
        w->Print(L" */");
    }
Ejemplo n.º 9
0
void cBlockPistonHandler::RetractPiston(Vector3i a_BlockPos, cWorld * a_World)
{
	BLOCKTYPE pistonBlock;
	NIBBLETYPE pistonMeta;
	a_World->GetBlockTypeMeta(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, pistonBlock, pistonMeta);

	if (!IsExtended(pistonMeta))
	{
		// Already retracted, bail out
		return;
	}

	Vector3i pushDir = MetadataToOffset(pistonMeta);

	// Check the extension:
	Vector3i extensionPos = a_BlockPos + pushDir;
	if (a_World->GetBlock(extensionPos) != E_BLOCK_PISTON_EXTENSION)
	{
		LOGD("%s: Piston without an extension - still extending, or just in an invalid state?", __FUNCTION__);
		return;
	}

	// Remove Extension
	a_World->SetBlock(extensionPos.x, extensionPos.y, extensionPos.z, E_BLOCK_AIR, 0);

	a_World->SetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, pistonBlock, pistonMeta & ~(8));
	a_World->BroadcastBlockAction(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, 1, pistonMeta & ~(8), pistonBlock);
	a_World->BroadcastSoundEffect("tile.piston.in", a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, 0.5f, 0.7f);

	if (!IsSticky(pistonBlock))
	{
		// No need for block pulling, bail out
		return;
	}

	// Get the block to pull
	a_BlockPos += pushDir * 2;
	// Try to "push" the pulling block in the opposite direction
	pushDir *= -1;

	Vector3iSet pushedBlocks;
	if (!CanPushBlock(a_BlockPos, a_World, false, pushedBlocks, pushDir))
	{
		// Not pushable, bail out
		return;
	}

	PushBlocks(pushedBlocks, a_World, pushDir);
}
Ejemplo n.º 10
0
void cBlockPistonHandler::RetractPiston(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World)
{
	BLOCKTYPE pistonBlock;
	NIBBLETYPE pistonMeta;
	a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, pistonBlock, pistonMeta);

	if (!IsExtended(pistonMeta))
	{
		// Already retracted, bail out
		return;
	}

	// Check the extension:
	AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, 1);
	if (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) != E_BLOCK_PISTON_EXTENSION)
	{
		LOGD("%s: Piston without an extension - still extending, or just in an invalid state?", __FUNCTION__);
		return;
	}

	AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, -1);
	a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, pistonBlock, pistonMeta & ~(8));
	a_World->BroadcastBlockAction(a_BlockX, a_BlockY, a_BlockZ, 1, pistonMeta & ~(8), pistonBlock);
	a_World->BroadcastSoundEffect("tile.piston.in", static_cast<double>(a_BlockX), static_cast<double>(a_BlockY), static_cast<double>(a_BlockZ), 0.5f, 0.7f);
	AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, 1);

	// Retract the extension, pull block if appropriate
	if (IsSticky(pistonBlock))
	{
		int tempx = a_BlockX, tempy = a_BlockY, tempz = a_BlockZ;
		AddPistonDir(tempx, tempy, tempz, pistonMeta, 1);
		BLOCKTYPE tempBlock;
		NIBBLETYPE tempMeta;
		a_World->GetBlockTypeMeta(tempx, tempy, tempz, tempBlock, tempMeta);
		if (CanPull(tempBlock, tempMeta))
		{
			// Pull the block
			a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, tempBlock, tempMeta);
			a_World->SetBlock(tempx, tempy, tempz, E_BLOCK_AIR, 0);
			return;
		}
	}
	
	// Retract without pulling
	a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
}
Ejemplo n.º 11
0
void cBlockPistonHandler::ExtendPiston(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World)
{
	BLOCKTYPE pistonBlock;
	NIBBLETYPE pistonMeta;
	a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, pistonBlock, pistonMeta);

	if (IsExtended(pistonMeta))
	{
		// Already extended, bail out
		return;
	}

	int dist = FirstPassthroughBlock(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, a_World);
	if (dist < 0)
	{
		// FirstPassthroughBlock says piston can't push anything, bail out
		return;
	}

	a_World->BroadcastBlockAction(a_BlockX, a_BlockY, a_BlockZ, 0, pistonMeta, pistonBlock);
	a_World->BroadcastSoundEffect("tile.piston.out", (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 0.5f, 0.7f);

	// Drop the breakable block in the line, if appropriate:
	AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, dist + 1);  // "a_Block" now at the breakable / empty block
	BLOCKTYPE currBlock;
	NIBBLETYPE currMeta;
	a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, currBlock, currMeta);
	if (currBlock != E_BLOCK_AIR)
	{
		cBlockHandler * Handler = BlockHandler(currBlock);
		if (Handler->DoesDropOnUnsuitable())
		{
			cChunkInterface ChunkInterface(a_World->GetChunkMap());
			cBlockInServerPluginInterface PluginInterface(*a_World);
			Handler->DropBlock(ChunkInterface, *a_World, PluginInterface, NULL, a_BlockX, a_BlockY, a_BlockZ);
		}
	}

	// Push blocks, from the furthest to the nearest:
	int oldx = a_BlockX, oldy = a_BlockY, oldz = a_BlockZ;
	NIBBLETYPE currBlockMeta;
	std::vector<Vector3i> ScheduledBlocks;
	ScheduledBlocks.reserve(PISTON_MAX_PUSH_DISTANCE);

	for (int i = dist + 1; i > 1; i--)
	{
		AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, -1);
		a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, currBlock, currBlockMeta);
		a_World->SetBlock(oldx, oldy, oldz, currBlock, currBlockMeta, false);
		ScheduledBlocks.push_back(Vector3i(oldx, oldy, oldz));
		oldx = a_BlockX;
		oldy = a_BlockY;
		oldz = a_BlockZ;
	}

	int extx = a_BlockX;
	int exty = a_BlockY;
	int extz = a_BlockZ;
	ScheduledBlocks.push_back(Vector3i(extx, exty, extz));
	AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, -1);
	// "a_Block" now at piston body, "ext" at future extension

	a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, pistonBlock, pistonMeta | 0x8);
	a_World->SetBlock(extx, exty, extz, E_BLOCK_PISTON_EXTENSION, pistonMeta | (IsSticky(pistonBlock) ? 8 : 0), false);
	a_World->ScheduleTask(PISTON_TICK_DELAY, new cWorld::cTaskSendBlockToAllPlayers(ScheduledBlocks));
}
Ejemplo n.º 12
0
void cBlockPistonHandler::ExtendPiston(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World)
{
	BLOCKTYPE pistonBlock;
	NIBBLETYPE pistonMeta;
	a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, pistonBlock, pistonMeta);

	if (IsExtended(pistonMeta))
	{
		// Already extended, bail out
		return;
	}

	int dist = FirstPassthroughBlock(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, a_World);
	if (dist < 0)
	{
		// FirstPassthroughBlock says piston can't push anything, bail out
		return;
	}

	a_World->BroadcastBlockAction(a_BlockX, a_BlockY, a_BlockZ, 0, pistonMeta, pistonBlock);
	a_World->BroadcastSoundEffect("tile.piston.out", static_cast<double>(a_BlockX), static_cast<double>(a_BlockY), static_cast<double>(a_BlockZ), 0.5f, 0.7f);

	// Drop the breakable block in the line, if appropriate:
	AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, dist + 1);  // "a_Block" now at the breakable / empty block
	BLOCKTYPE currBlock;
	NIBBLETYPE currMeta;
	a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, currBlock, currMeta);
	if (currBlock != E_BLOCK_AIR)
	{
		cBlockHandler * Handler = BlockHandler(currBlock);
		if (Handler->DoesDropOnUnsuitable())
		{
			cChunkInterface ChunkInterface(a_World->GetChunkMap());
			cBlockInServerPluginInterface PluginInterface(*a_World);
			Handler->DropBlock(ChunkInterface, *a_World, PluginInterface, nullptr, a_BlockX, a_BlockY, a_BlockZ);
		}
	}

	// Push blocks, from the furthest to the nearest:
	int oldx = a_BlockX, oldy = a_BlockY, oldz = a_BlockZ;
	NIBBLETYPE currBlockMeta;

	for (int i = dist + 1; i > 1; i--)
	{
		AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, -1);
		a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, currBlock, currBlockMeta);
		a_World->SetBlock(oldx, oldy, oldz, currBlock, currBlockMeta);
		oldx = a_BlockX;
		oldy = a_BlockY;
		oldz = a_BlockZ;
	}

	int extx = a_BlockX;
	int exty = a_BlockY;
	int extz = a_BlockZ;
	AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, -1);
	// "a_Block" now at piston body, "ext" at future extension

	a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, pistonBlock, pistonMeta | 0x8);
	a_World->SetBlock(extx, exty, extz, E_BLOCK_PISTON_EXTENSION, pistonMeta | (IsSticky(pistonBlock) ? 8 : 0));
}