package com.carpentersblocks.data;
import java.util.HashSet;
import java.util.Set;
import net.minecraft.block.Block;
import net.minecraftforge.common.util.ForgeDirection;
import com.carpentersblocks.tileentity.TEBase;
import com.carpentersblocks.util.BlockProperties;
import com.carpentersblocks.util.registry.FeatureRegistry;
public abstract class AbstractMultiBlock {
/**
* Gathers adjacent blocks based on specific criteria, enabling
* a group of blocks to act as a single entity when interacting
* with only a single block.
*
* @param TE the {@link TEBase}
* @param block the {@link Block} to match against
* @return a {@link Set} of parts
* @see {@link #getMatchingDataPattern}
*/
public final Set<TEBase> getBlocks(TEBase TE, Block block)
{
Set<TEBase> set = new HashSet<TEBase>();
int matchData = getMatchingDataPattern(TE);
ForgeDirection[] dirs = getLocateDirs(TE);
addAndLocateBlocks(TE, block, matchData, dirs, set);
return set;
}
/**
* Adds {@link TEBase} object to set, and continues locating additional
* blocks that are part of structure.
*
* @param TE the {@link TEBase}
* @param block the {@link Block} type to locate
* @param matchData the {@link #getMatchingDataPattern data mask} to match against
* @param dirs the {@link #getLocateDirs directions} to search
* @param set the {@link Set} of blocks
*/
private void addAndLocateBlocks(TEBase TE, Block block, int matchData, ForgeDirection[] dirs, Set<TEBase> set)
{
if (set.size() > FeatureRegistry.multiBlockSizeLimit) {
return;
}
if (set.contains(TE)) {
return;
}
// Add piece to final set
set.add(TE);
// Locate additional blocks
for (ForgeDirection dir : dirs) {
TEBase TE_adj = BlockProperties.getTileEntity(block, TE.getWorldObj(), TE.xCoord - dir.offsetX, TE.yCoord - dir.offsetY, TE.zCoord - dir.offsetZ);
if (TE_adj != null && (TE_adj.getData() & matchData) == matchData) {
addAndLocateBlocks(TE_adj, block, matchData, dirs, set);
}
}
}
/**
* Used to match against adjacent block data when determining
* whether a connection can be made.
* <p>
* Supplies an integer mask to logical AND with candidate
* block data.
*
* @return an integer
*/
abstract public int getMatchingDataPattern(TEBase TE);
/**
* Grabs an array of valid {@link ForgeDirection ForgeDirections}
* used when locating additional pieces for block in a
* two-dimensional space.
*
* @param TE the {@link TEBase}
* @return an array of supported {@link ForgeDirection ForgeDirections}
*/
abstract public ForgeDirection[] getLocateDirs(TEBase TE);
}