Skip to content

Instantly share code, notes, and snippets.

@StillManic
Created August 12, 2015 23:59
Show Gist options
  • Save StillManic/38ff8b19bf62921a7c2f to your computer and use it in GitHub Desktop.
Save StillManic/38ff8b19bf62921a7c2f to your computer and use it in GitHub Desktop.
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});
}
}
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);
}
}
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());
}
}
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;
}
}
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;
}
};
}
};
}
}
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;
}
}
}
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