Created
August 12, 2015 23:59
-
-
Save StillManic/38ff8b19bf62921a7c2f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import net.minecraft.block.Block; | |
import net.minecraft.block.material.Material; | |
import net.minecraft.block.properties.IProperty; | |
import net.minecraft.block.properties.PropertyBool; | |
import net.minecraft.block.properties.PropertyDirection; | |
import net.minecraft.block.state.BlockState; | |
import net.minecraft.block.state.IBlockState; | |
import net.minecraft.creativetab.CreativeTabs; | |
import net.minecraft.entity.EntityLivingBase; | |
import net.minecraft.entity.player.EntityPlayer; | |
import net.minecraft.item.ItemStack; | |
import net.minecraft.util.BlockPos; | |
import net.minecraft.util.EnumFacing; | |
import net.minecraft.util.MathHelper; | |
import net.minecraft.world.World; | |
import net.minecraftforge.fml.relauncher.Side; | |
import net.minecraftforge.fml.relauncher.SideOnly; | |
import shadekiller666.multiblock.MultiBlockFacing; | |
import shadekiller666.multiblock.MultiBlockMain; | |
public class MultiBlock extends Block { | |
public static final MultiBlock instance = new MultiBlock(); | |
public static final String name = "multiblock"; | |
public static final PropertyDirection FACING = PropertyDirection.create("facing"); | |
public static final PropertyDirection TOP = PropertyDirection.create("top"); | |
public static final PropertyBool FORMED = PropertyBool.create("formed"); | |
private MultiBlock() { | |
super(Material.iron); | |
this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, MultiBlockFacing.NORTH).withProperty(FORMED, Boolean.valueOf(false))); | |
this.setStepSound(soundTypePiston); | |
this.setHardness(0.5f); | |
setUnlocalizedName(MultiBlockMain.MODID + ":" + name); | |
setCreativeTab(CreativeTabs.tabBlock); | |
} | |
@Override | |
public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack) { | |
world.setBlockState(pos, state.withProperty(FACING, getFacingFromEntity(world, pos, placer)), 2); | |
} | |
@Override | |
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ) { | |
return true; | |
} | |
@Override | |
public void onNeighborBlockChange(World world, BlockPos pos, IBlockState state, Block neighborBlock) { | |
} | |
@Override | |
public void onBlockAdded(World world, BlockPos pos, IBlockState state) { | |
} | |
@Override | |
public IBlockState onBlockPlaced(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer) { | |
return this.getDefaultState().withProperty(FACING, getFacingFromEntity(world, pos, placer)).withProperty(FORMED, Boolean.valueOf(false)); | |
} | |
@Override | |
public boolean onBlockEventReceived(World world, BlockPos pos, IBlockState state, int eventID, int eventParam) { | |
MultiBlockFacing facing = MultiBlockFacing.getFacingFromEnum((EnumFacing) state.getValue(FACING)); | |
return false; | |
} | |
public static MultiBlockFacing getFacing(int meta) { | |
int j = meta & 7; | |
return j > 5 ? null : MultiBlockFacing.getOrientation(j); | |
} | |
public static EnumFacing getFacingFromEntity(World world, BlockPos pos, EntityLivingBase entity) { | |
if (MathHelper.abs((float) entity.posX - (float) pos.getX()) < 2.0f && MathHelper.abs((float) entity.posZ - (float) pos.getZ()) < 2.0f) { | |
double offset = entity.posY + (double) entity.getEyeHeight(); | |
if (offset - (double) pos.getY() > 2.0d) { | |
return EnumFacing.UP; | |
} | |
if ((double) pos.getY() - offset > 2.0d) { | |
return EnumFacing.DOWN; | |
} | |
} | |
return entity.getHorizontalFacing().getOpposite(); | |
} | |
@Override | |
public IBlockState getStateFromMeta(int meta) { | |
return this.getDefaultState().withProperty(FACING, getFacing(meta)).withProperty(FORMED, Boolean.valueOf((meta & 8) > 0)); | |
} | |
@Override | |
@SideOnly(Side.CLIENT) | |
public IBlockState getStateForEntityRender(IBlockState state) { | |
return this.getDefaultState().withProperty(FACING, EnumFacing.UP); | |
} | |
public int getMetaFromState(IBlockState state) { | |
byte b0 = 0; | |
int i = b0 | ((EnumFacing) state.getValue(FACING)).getIndex(); | |
if (((Boolean) state.getValue(FORMED)).booleanValue()) { | |
i |= 8; | |
} | |
return i; | |
} | |
protected BlockState createBlockState() { | |
return new BlockState(this, new IProperty[] {FACING, FORMED}); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package shadekiller666.multiblock; | |
import com.google.common.base.Predicate; | |
import net.minecraft.block.Block; | |
import java.util.Arrays; | |
import java.util.List; | |
public class MultiBlockAlias implements Predicate { | |
private final List<Block> aliases; | |
public MultiBlockAlias(List<Block> aliases) { | |
this.aliases = aliases; | |
} | |
public MultiBlockAlias(Block[] aliases) { | |
this.aliases = Arrays.asList(aliases); | |
} | |
public List<Block> getAliases() { | |
return this.aliases; | |
} | |
@Override | |
public boolean apply(Object input) { | |
return this.aliases.contains(input); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package shadekiller666.multiblock; | |
import net.minecraft.util.EnumFacing; | |
public enum MultiBlockFacing { | |
DOWN(0, -1, 0), | |
UP(0, 1, 0), | |
NORTH(0, 0, -1), | |
SOUTH(0, 0, 1), | |
WEST(-1, 0, 0), | |
EAST(1, 0, 0), | |
UNKNOWN(0, 0, 0); | |
public final int offsetX; | |
public final int offsetY; | |
public final int offsetZ; | |
public final int flag; | |
public static final MultiBlockFacing[] VALID_DIRECTIONS = {DOWN, UP, NORTH, SOUTH, WEST, EAST}; | |
public static final int[] OPPOSITES = {1, 0, 3, 2, 5, 4, 6}; | |
public static final int[][] ROTATION_MATRIX_COUNTER = { | |
{0, 1, 4, 5, 3, 2, 6}, | |
{0, 1, 5, 4, 2, 3, 6}, | |
{5, 4, 2, 3, 0, 1, 6}, | |
{4, 5, 2, 3, 1, 0, 6}, | |
{2, 3, 1, 0, 4, 5, 6}, | |
{3, 2, 0, 1, 4, 5, 6}, | |
{0, 1, 2, 3, 4, 5, 6} | |
}; | |
public static final int[][] ROTATION_MATRIX_CLOCK = { | |
{0, 1, 5, 4, 2, 3, 6}, | |
{0, 1, 4, 5, 3, 2, 6}, | |
{4, 5, 2, 3, 1, 0, 6}, | |
{5, 4, 2, 3, 0, 1, 6}, | |
{3, 2, 0, 1, 4, 5, 6}, | |
{2, 3, 1, 0, 4, 5, 6}, | |
{0, 1, 2, 3, 4, 5, 6} | |
}; | |
private MultiBlockFacing(int x, int y, int z) { | |
offsetX = x; | |
offsetY = y; | |
offsetZ = z; | |
flag = 1 << ordinal(); | |
} | |
public static MultiBlockFacing getOrientation(int id) { | |
if (id >= 0 && id < VALID_DIRECTIONS.length) { | |
return VALID_DIRECTIONS[id]; | |
} | |
return UNKNOWN; | |
} | |
public MultiBlockFacing getOpposite() { | |
return getOrientation(OPPOSITES[ordinal()]); | |
} | |
public MultiBlockFacing getRotationCounter(MultiBlockFacing axis) { | |
return getOrientation(ROTATION_MATRIX_COUNTER[axis.ordinal()][ordinal()]); | |
} | |
public MultiBlockFacing getRotationClock(MultiBlockFacing axis) { | |
return getOrientation(ROTATION_MATRIX_CLOCK[axis.ordinal()][ordinal()]); | |
} | |
public static MultiBlockFacing getFacingFromEnum(EnumFacing facing) { | |
return getOrientation(facing.ordinal()); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package shadekiller666.multiblock; | |
import com.google.common.collect.BiMap; | |
import com.google.common.collect.HashBiMap; | |
import net.minecraft.util.BlockPos; | |
import net.minecraft.util.Vec3i; | |
import java.util.HashMap; | |
import java.util.Iterator; | |
import java.util.Map; | |
public final class MultiBlockManager { | |
public static final MultiBlockManager instance = new MultiBlockManager(); | |
private static Map<BlockPos, MultiBlockStructure> structureMap = new HashMap<BlockPos, MultiBlockStructure>(); | |
private static Map<String, MultiBlockTemplate> templateMap = new HashMap<String, MultiBlockTemplate>(); | |
private static BiMap<MultiBlockTemplate, MultiBlockStructure> registry = HashBiMap.create(); | |
public void registerTemplate(MultiBlockTemplate template) { | |
if (!templateMap.containsKey(template.getName())) { | |
templateMap.put(template.getName(), template); | |
} | |
} | |
public void createStructure(BlockPos pos, Vec3i dimensions, MultiBlockFacing facing, MultiBlockFacing top, MultiBlockTemplate template) { | |
MultiBlockStructure structure = new MultiBlockStructure(pos, dimensions, facing, top, template.getName()); | |
structureMap.put(pos, structure); | |
registry.put(template, structure); | |
} | |
public MultiBlockTemplate getTemplate(String name) { | |
return templateMap.get(name); | |
} | |
public MultiBlockStructure getStructure(BlockPos pos) { | |
return structureMap.get(pos); | |
} | |
public boolean isStructureFormed(BlockPos pos, boolean isPosMaster) { | |
if (structureMap.containsKey(pos)) { | |
MultiBlockStructure structure = structureMap.get(pos); | |
MultiBlockTemplate template = registry.inverse().get(structure); | |
if (isPosMaster) { | |
} | |
} | |
return false; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package shadekiller666.multiblock; | |
import com.google.common.collect.AbstractIterator; | |
import net.minecraft.util.BlockPos; | |
import net.minecraft.util.Vec3i; | |
import java.util.ArrayList; | |
import java.util.Iterator; | |
import java.util.List; | |
public class MultiBlockStructure { | |
private BlockPos position; | |
private MultiBlockFacing top; | |
private MultiBlockFacing front; | |
private final String templateName; | |
private Vec3i dimensions; | |
protected MultiBlockStructure(BlockPos pos, Vec3i dimensions, MultiBlockFacing front, MultiBlockFacing top, String templateName) { | |
this.position = pos; | |
this.dimensions = dimensions; | |
this.front = front; | |
this.top = top; | |
this.templateName = templateName; | |
} | |
public String getTemplateName() { | |
return this.templateName; | |
} | |
public BlockPos getPosition() { | |
return this.position; | |
} | |
public void setDimensions(Vec3i dimensions) { | |
this.dimensions = dimensions; | |
} | |
public Vec3i getDimensions() { | |
return this.dimensions; | |
} | |
public void setPosition(BlockPos position) { | |
this.position = position; | |
} | |
public void setFront(MultiBlockFacing front) { | |
this.front = front; | |
} | |
public MultiBlockFacing getFront() { | |
return this.front; | |
} | |
public void setTop(MultiBlockFacing top) { | |
this.top = top; | |
} | |
public MultiBlockFacing getTop() { | |
return this.top; | |
} | |
public static Iterable getAllInBox(BlockPos from, BlockPos to) { | |
final BlockPos min = new BlockPos(Math.min(from.getX(), to.getX()), Math.min(from.getY(), to.getY()), Math.min(from.getZ(), to.getZ())); | |
final BlockPos max = new BlockPos(Math.max(from.getX(), to.getX()), Math.max(from.getY(), to.getY()), Math.max(from.getZ(), to.getZ())); | |
return new Iterable() { | |
@Override | |
public Iterator iterator() { | |
return new AbstractIterator() { | |
private BlockPos lastReturned = null; | |
private int lastIndex = -1; | |
@Override | |
protected Object computeNext() { | |
if (this.lastReturned == null) { | |
this.lastIndex = 0; | |
this.lastReturned = min; | |
return this.lastReturned; | |
} else if (this.lastReturned.equals(max)) { | |
this.lastIndex++; | |
return (BlockPos) this.endOfData(); | |
} else { | |
this.lastIndex++; | |
int i = this.lastReturned.getX(); | |
int j = this.lastReturned.getY(); | |
int k = this.lastReturned.getZ(); | |
if (i < max.getX()) { | |
i++; | |
} else if (k < max.getZ()) { | |
i = min.getX(); | |
k++; | |
} else if (j < max.getY()) { | |
i = min.getX(); | |
k = min.getZ(); | |
j++; | |
} | |
this.lastReturned = new BlockPos(i, j, k); | |
return this.lastReturned; | |
} | |
} | |
protected int getLastIndex() { | |
return this.lastIndex; | |
} | |
}; | |
} | |
}; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package shadekiller666.multiblock; | |
import com.google.common.collect.AbstractIterator; | |
import net.minecraft.block.Block; | |
import net.minecraft.init.Blocks; | |
import net.minecraft.util.Vec3i; | |
import javax.vecmath.Vector3f; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.Iterator; | |
import java.util.List; | |
public class MultiBlockTemplate { | |
private List<List<List>> template = new ArrayList<List<List>>(); | |
private Vec3i dimensions = new Vec3i(-1, -1, -1); | |
private int layers = -1; | |
private int columns = -1; | |
private int rows = -1; | |
private boolean hasMaster; | |
private Vec3i masterLocation = new Vec3i(-1, -1, -1); | |
private int masterLayer = -1; | |
private int masterColumn = -1; | |
private int masterRow = -1; | |
private Block master; | |
private final String name; | |
private MultiBlockFacing front = MultiBlockFacing.NORTH; | |
private MultiBlockFacing top = MultiBlockFacing.UP; | |
public MultiBlockTemplate(String name) { | |
this.name = name; | |
} | |
public String getName() { | |
return this.name; | |
} | |
@SuppressWarnings("unchecked") | |
public void addLayer(Block master, Object... objs) { | |
//TODO: add support for defining variant of blocks (ie. stone v andesite) | |
this.layers++; | |
String s = ""; | |
int i, j, k; | |
i = k = j = 0; | |
/* Parse Template Strings */ | |
if (objs[1] instanceof String[]) { | |
String[] strings = (String[]) objs[1]; | |
this.rows = strings.length; | |
for (int l = 0; l < strings.length; l++) { | |
String s1 = strings[l]; | |
this.columns = s1.length(); | |
++k; | |
j = s1.length(); | |
s = s + s1; | |
} | |
} else { | |
while (objs[i] instanceof String) { | |
this.rows++; | |
String s2 = (String) objs[i++]; | |
this.columns = s2.length(); | |
++k; | |
j = s2.length(); | |
s = s + s2; | |
} | |
} | |
/* Parse and Assign Characters With Block Instances */ | |
HashMap map; | |
Block block = null; | |
MultiBlockAlias alias = null; | |
Character masterChar = '\0'; //unicode 0 | |
for (map = new HashMap(); i < objs.length; i += 2) { | |
block = null; | |
alias = null; | |
Character character = (Character) objs[1]; | |
if (objs[i + 1] instanceof Block) { | |
block = (Block) objs[i + 1]; | |
} else if (objs[i + 1] instanceof Block[]) { | |
alias = new MultiBlockAlias((Block[]) objs[i + 1]); | |
} else if (objs[i + 1] instanceof MultiBlockAlias) { | |
alias = (MultiBlockAlias) objs[i + 1]; | |
} | |
if (master != null) { | |
if (this.master == null) { | |
this.hasMaster = false; | |
if (block != null && Block.isEqualTo(block, master)) { | |
this.hasMaster = true; | |
this.master = block; | |
masterChar = character; | |
} | |
} else { | |
this.hasMaster = false; | |
} | |
} | |
if (Character.isSpaceChar(character)) { | |
block = Blocks.air; | |
} | |
map.put(character, block != null ? block : alias); | |
} | |
/* Create Layer Using Block from HashMap */ | |
Object[] entries = new Object[j * k]; | |
char dummyChar = '\0'; //unicode 0 | |
for (int i1 = 0; i1 < j * k; i1++) { | |
char c0 = s.charAt(i1); | |
if (c0 == '?') { | |
dummyChar = c0; | |
} | |
if (map.containsKey(Character.valueOf(c0))) { | |
if (!this.hasMaster) { | |
this.masterColumn = -1; | |
this.masterLayer = -1; | |
this.masterRow = -1; | |
} else { | |
if (block != null && (Block.isEqualTo(block, this.master) || (c0 == masterChar && c0 != dummyChar))) { | |
this.masterColumn = i1 % j; | |
this.masterLayer = layers; | |
this.masterRow = i1 / k; | |
} | |
} | |
entries[i1] = c0 == dummyChar ? null : (map.get(Character.valueOf(c0)) instanceof Block ? (Block) map.get(Character.valueOf(c0)) : (MultiBlockAlias) map.get(Character.valueOf(c0))); | |
} else { | |
entries[i1] = Blocks.air; | |
} | |
} | |
this.template = this.template != null ? this.template : new ArrayList<List<List>>(); | |
this.template.add(this.layers, new ArrayList<List>()); | |
for (int row = 0; row < this.rows; row++) { | |
this.template.get(layers).add(row, new ArrayList()); | |
for (int col = 0; col < this.columns; col++) { | |
this.template.get(layers).get(row).add(col, entries[row * col]); | |
} | |
} | |
this.dimensions = new Vec3i(this.columns, this.layers, this.rows); | |
this.masterLocation = new Vec3i(this.masterColumn, this.masterLayer, this.masterRow); | |
} | |
public Vec3i getDimensions() { | |
return this.dimensions; | |
} | |
public boolean getHasMaster() { | |
return this.hasMaster; | |
} | |
public Block getMaster() { | |
return this.master; | |
} | |
public Vec3i getMasterLocation() { | |
return this.masterLocation; | |
} | |
public List getTemplate() { | |
return this.template; | |
} | |
public boolean isContainedInTemplate(Block block) { | |
for (List<List> l : this.template) { | |
for (List r : l) { | |
for (Object c : r) { | |
if (c instanceof Block && Block.isEqualTo(block, (Block) c)) { | |
return true; | |
} else if (c instanceof MultiBlockAlias) { | |
MultiBlockAlias alias = (MultiBlockAlias) c; | |
for (Block b : alias.getAliases()) { | |
if (Block.isEqualTo(block, b)) { | |
return true; | |
} | |
} | |
} | |
} | |
} | |
} | |
return false; | |
} | |
public Iterator getIterator() { | |
return new Iterator() { | |
int c = 0; | |
int l = 0; | |
int r = 0; | |
@Override | |
public boolean hasNext() { | |
return (c != columns) && (l != layers) && (r != rows); | |
} | |
@Override | |
public Object next() { | |
Object object = template.get(l).get(r).get(c); | |
if (c < columns) { | |
c++; | |
} else if (r < rows) { | |
c = 0; | |
r++; | |
} else if (l < layers) { | |
c = 0; | |
r = 0; | |
l++; | |
} | |
return object; | |
} | |
@Override | |
public void remove() {} | |
}; | |
} | |
public MultiBlockTemplate rotateTo(MultiBlockFacing front, MultiBlockFacing top) { | |
if (front == this.front && top == this.top) { | |
return this; | |
} else { | |
if (front == this.front) ; | |
return null; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package shadekiller666.multiblock.tile_entities; | |
import net.minecraft.block.Block; | |
import net.minecraft.block.state.IBlockState; | |
import net.minecraft.init.Blocks; | |
import net.minecraft.nbt.NBTTagCompound; | |
import net.minecraft.server.gui.IUpdatePlayerListBox; | |
import net.minecraft.tileentity.TileEntity; | |
import net.minecraft.util.EnumFacing; | |
import net.minecraft.util.Vec3i; | |
import shadekiller666.multiblock.MultiBlockManager; | |
import shadekiller666.multiblock.MultiBlockTemplate; | |
import shadekiller666.multiblock.blocks.MultiBlock; | |
public class MultiBlockTileEntity extends TileEntity implements IUpdatePlayerListBox { | |
private IBlockState state; | |
private EnumFacing facing; | |
private boolean formed; | |
private MultiBlockTemplate template = new MultiBlockTemplate("test"); | |
public MultiBlockTileEntity() { | |
initTemplate(); | |
} | |
public MultiBlockTileEntity(IBlockState state, EnumFacing facing, boolean formed) { | |
this.state = state; | |
this.facing = facing; | |
this.formed = formed; | |
initTemplate(); | |
} | |
private void initTemplate() { | |
this.template.addLayer(null, "OOOOO", "OSSSO", "OSSSO", "OSSSO", "OOOOO", 'S', Blocks.stone, 'O', Blocks.obsidian); | |
this.template.addLayer(null, "OSSSO", "S S", "S S", "S S", "OSSSO", 'S', Blocks.stone, 'O', Blocks.obsidian); | |
this.template.addLayer(MultiBlock.instance, "OSMSO", "S S", "S S", "S S", "OSSSO", 'S', Blocks.stone, 'O', Blocks.obsidian, 'M', MultiBlock.instance); | |
this.template.addLayer(null, "OSSSO", "S S", "S S", "S S", "OSSSO", 'S', Blocks.stone, 'O', Blocks.obsidian); | |
this.template.addLayer(null, "OOOOO", "OSSSO", "OSSSO", "OSSSO", "OOOOO", 'S', Blocks.stone, 'O', Blocks.obsidian); | |
MultiBlockManager.instance.registerTemplate(this.template); | |
MultiBlockManager.instance.createStructure(this.getPos(), new Vec3i(5, 5, 5), this.facing, ); | |
} | |
public IBlockState getState() { | |
return this.state; | |
} | |
public int getBlockMetadata() { | |
return 0; | |
} | |
public EnumFacing getFacing() { | |
return this.facing; | |
} | |
@Override | |
public void update() {} | |
@Override | |
public void readFromNBT(NBTTagCompound compound) { | |
super.readFromNBT(compound); | |
this.state = Block.getBlockById(compound.getInteger("blockId")).getStateFromMeta(compound.getInteger("blockData")); | |
this.facing = EnumFacing.getFront(compound.getInteger("facing")); | |
this.formed = compound.getBoolean("formed"); | |
} | |
@Override | |
public void writeToNBT(NBTTagCompound compound) { | |
super.writeToNBT(compound); | |
compound.setInteger("blockId", Block.getIdFromBlock(this.state.getBlock())); | |
compound.setInteger("blockData", this.state.getBlock().getMetaFromState(this.state)); | |
compound.setInteger("facing", this.facing.getIndex()); | |
compound.setBoolean("formed", this.formed); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment