示例#1
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);
}
示例#2
0
void cVillager::HandleFarmerTryHarvestCrops()
{
	// Harvest the crops if the villager isn't moving and if the crops are closer then 2 blocks.
	if (!m_PathfinderActivated && (GetPosition() - m_CropsPos).Length() < 2)
	{
		// Check if the blocks didn't change while the villager was walking to the coordinates.
		BLOCKTYPE CropBlock = m_World->GetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z);
		if (IsBlockFarmable(CropBlock) && m_World->GetBlockMeta(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z) == 0x7)
		{
			cBlockHandler * Handler = cBlockInfo::GetHandler(CropBlock);
			cChunkInterface ChunkInterface(m_World->GetChunkMap());
			cBlockInServerPluginInterface PluginInterface(*m_World);
			Handler->DropBlock(ChunkInterface, *m_World, PluginInterface, this, m_CropsPos.x, m_CropsPos.y, m_CropsPos.z);
			m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_AIR, 0);
			m_ActionCountDown = 20;
		}
	}
}
示例#3
0
void cItemHandler::OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ)
{
	UNUSED(a_Item);
	
	BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
	cBlockHandler * Handler = cBlockInfo::GetHandler(Block);

	if (a_Player->IsGameModeSurvival())
	{
		if (!BlockRequiresSpecialTool(Block) || CanHarvestBlock(Block))
		{
			cChunkInterface ChunkInterface(a_World->GetChunkMap());
			cBlockInServerPluginInterface PluginInterface(*a_World);
			Handler->DropBlock(ChunkInterface, *a_World, PluginInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ);
		}
	}
	
	a_Player->UseEquippedItem();
}
示例#4
0
void cItemHandler::OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ)
{
	UNUSED(a_Item);
	
	BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
	cBlockHandler * Handler = cBlockInfo::GetHandler(Block);

	if (a_Player->IsGameModeSurvival())
	{
		cChunkInterface ChunkInterface(a_World->GetChunkMap());
		cBlockInServerPluginInterface PluginInterface(*a_World);
		Handler->DropBlock(ChunkInterface, *a_World, PluginInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ, CanHarvestBlock(Block));
	}

	if (!cBlockInfo::IsOneHitDig(Block))
	{
		a_Player->UseEquippedItem(GetDurabilityLossByAction(dlaBreakBlock));
	}
}
示例#5
0
void cBlockPistonHandler::PushBlocks(
	const Vector3iSet & a_BlocksToPush,
	cWorld * a_World, const Vector3i & a_PushDir
)
{
	// Sort blocks to move the blocks first, which are farest away from the piston
	// This prevents the overwriting of existing blocks
	std::vector<Vector3i> sortedBlocks(a_BlocksToPush.begin(), a_BlocksToPush.end());
	std::sort(sortedBlocks.begin(), sortedBlocks.end(), [a_PushDir](const Vector3i & a, const Vector3i & b)
	{
		return a.Dot(a_PushDir) > b.Dot(a_PushDir);
	});

	// Move every block
	BLOCKTYPE moveBlock;
	NIBBLETYPE moveMeta;
	for (auto & moveBlockPos : sortedBlocks)
	{
		a_World->GetBlockTypeMeta(moveBlockPos.x, moveBlockPos.y, moveBlockPos.z, moveBlock, moveMeta);
		a_World->SetBlock(moveBlockPos.x, moveBlockPos.y, moveBlockPos.z, E_BLOCK_AIR, 0);

		moveBlockPos += a_PushDir;
		if (cBlockInfo::IsPistonBreakable(moveBlock))
		{
			// Block is breakable, drop it
			cBlockHandler * Handler = BlockHandler(moveBlock);
			if (Handler->DoesDropOnUnsuitable())
			{
				cChunkInterface ChunkInterface(a_World->GetChunkMap());
				cBlockInServerPluginInterface PluginInterface(*a_World);
				Handler->DropBlock(ChunkInterface, *a_World, PluginInterface, nullptr,
					moveBlockPos.x, moveBlockPos.y, moveBlockPos.z
				);
			}
		} else
		{
			// Not breakable, just move it
			a_World->SetBlock(moveBlockPos.x, moveBlockPos.y, moveBlockPos.z, moveBlock, moveMeta);
		}
	}
}
void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta)
{
	ASSERT(a_NewMeta <= 8);  // Invalid meta values
	ASSERT(a_NewMeta > 0);  // Source blocks aren't spread

	a_NearChunk = a_NearChunk->GetRelNeighborChunkAdjustCoords(a_RelX, a_RelZ);
	if ((a_NearChunk == NULL) || (!a_NearChunk->IsValid()))
	{
		// Chunk not available
		return;
	}

	const int BlockX = a_NearChunk->GetPosX() * cChunkDef::Width + a_RelX;
	const int BlockZ = a_NearChunk->GetPosZ() * cChunkDef::Width + a_RelZ;
	
	BLOCKTYPE BlockType;
	NIBBLETYPE BlockMeta;
	a_NearChunk->GetBlockTypeMeta(a_RelX, a_RelY, a_RelZ, BlockType, BlockMeta);
	
	if (IsAllowedBlock(BlockType))
	{
		if ((BlockMeta == a_NewMeta) || IsHigherMeta(BlockMeta, a_NewMeta))
		{
			// Don't spread there, there's already a higher or same level there
			return;
		}
	}

	// Check water - lava interaction:
	if (m_FluidBlock == E_BLOCK_LAVA)
	{
		if (IsBlockWater(BlockType))
		{
			// Lava flowing into water, change to stone / cobblestone based on direction:
			BLOCKTYPE NewBlock = (a_NewMeta == 8) ? E_BLOCK_STONE : E_BLOCK_COBBLESTONE;
			FLOG("  Lava flowing into water, turning water at rel {%d, %d, %d} into stone", 
				a_RelX, a_RelY, a_RelZ,
				ItemTypeToString(NewBlock).c_str()
			);
			a_NearChunk->SetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0);

			a_NearChunk->BroadcastSoundEffect("random.fizz", BlockX * 8, a_RelY * 8, BlockZ * 8, 0.5f, 1.5f);
			return;
		}
	}
	else if (m_FluidBlock == E_BLOCK_WATER)
	{
		if (IsBlockLava(BlockType))
		{
			// Water flowing into lava, change to cobblestone / obsidian based on dest block:
			BLOCKTYPE NewBlock = (BlockMeta == 0) ? E_BLOCK_OBSIDIAN : E_BLOCK_COBBLESTONE;
			FLOG("  Water flowing into lava, turning lava at rel {%d, %d, %d} into %s", 
				a_RelX, a_RelY, a_RelZ, ItemTypeToString(NewBlock).c_str()
			);
			a_NearChunk->SetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0);

			a_NearChunk->BroadcastSoundEffect("random.fizz", BlockX * 8, a_RelY * 8, BlockZ * 8, 0.5f, 1.5f);
			return;
		}
	}
	else
	{
		ASSERT(!"Unknown fluid!");
	}
	
	if (!IsPassableForFluid(BlockType))
	{
		// Can't spread there
		return;
	}
	
	// Wash away the block there, if possible:
	if (CanWashAway(BlockType))
	{
		cBlockHandler * Handler = BlockHandler(BlockType);
		if (Handler->DoesDropOnUnsuitable())
		{
			cChunkInterface ChunkInterface(m_World.GetChunkMap());
			cBlockInServerPluginInterface PluginInterface(m_World);
			Handler->DropBlock(
				ChunkInterface,
				m_World,
				PluginInterface,
				NULL, 
				BlockX, 
				a_RelY,
				BlockZ
			);
		}
	}  // if (CanWashAway)

	// Spread:
	FLOG("  Spreading to {%d, %d, %d} with meta %d", BlockX, a_RelY, BlockZ, a_NewMeta);
	a_NearChunk->SetBlock(a_RelX, a_RelY, a_RelZ, m_FluidBlock, a_NewMeta);
	m_World.GetSimulatorManager()->WakeUp(BlockX, a_RelY, BlockZ, a_NearChunk);

	HardenBlock(a_NearChunk, a_RelX, a_RelY, a_RelZ, m_FluidBlock, a_NewMeta);
}
示例#7
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));
}
示例#8
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));
}