Хочу ковер, который соединяется по краям и по углам с соседними коврами, пригодится для декораций. Его можно вешать на стену, на потолок, слать по углам.
Уже сделаны 3 стадии прорисовки:
1. Собственно, ковер.
2. Соединение с соседними коврами по краям.
3. Соединение с соседними коврами по углам.
Теперь надо добавить ambient occlusion.
 Первая стадия
 Первая стадия Вторая стадия
 Вторая стадия Третья стадия
 Третья стадия Теперь цветной
 Теперь цветной ДА!!! Это то, чего вы так долго ждали!
 ДА!!! Это то, чего вы так долго ждали!Без коментариев

Сделал текстурку поколоритнее, цвета можно комбинировать:
Ковры соединяются с собой в бесконечном количестве, т.е. вы сможете постелить дома здоровенный ковер 5х5 или постелить длиннющий вдоль дорожки 20х2 к вашему гробу. Или обстелить весь гроб к черту, хоть какое-то разнообразие будет.
Ловушку с помощью ковра не сделать, потому что ковер стелится там, где есть блок.
Даже не знаю как быть со ступеньками, полублоками и косыми блоками. Надо будет что-то придумать.
 Крафты
 Крафты Код в настоящий момент. НЕ последняя версия, просто для ознакомления
 Код в настоящий момент. НЕ последняя версия, просто для ознакомленияЛицензия WTFPL.
 BlockCarpet.java целиком
 BlockCarpet.java целикомpackage net.minecraft.src;
import java.util.List;
import java.util.Random;
public class BlockCarpet extends Block
{
	public static final int[][] carpetColors = {
		{ 221, 221, 221, },
		{ 219, 125, 62, },
		{ 179, 80, 188 },
		{ 107, 138, 201, },
		{ 177, 166, 39, },
		{ 65, 174, 56, },
		{ 208, 132, 153, },
		{ 64, 64, 64, },
		{ 154, 161, 161, },
		{ 46, 110, 137, },
		{ 126, 61, 181, },
		{ 46, 56, 141, },
		{ 79, 50, 31, },
		{ 53, 70, 27, },
		{ 150, 52, 48, },
		{ 25, 22, 22, },
	};
	public int fillTextureIndex;
	public int sidesTextureIndex;
	public boolean colored;
	
    protected BlockCarpet(int blockId, int baseTextureIndex, int sidesTextureIndex, int fillTextureIndex, boolean colored)
    {
        super(blockId, baseTextureIndex, Material.cloth);
        this.setCreativeTab(CreativeTabs.tabDeco);
        this.fillTextureIndex = fillTextureIndex;
        this.sidesTextureIndex = sidesTextureIndex;
        this.colored = colored;
    }
    public int getRenderColor(int damage)
    {
    	return !colored ? 0xffffff :
    			((carpetColors[damage][0] & 0xff) ‹‹ 16) |
    			((carpetColors[damage][1] & 0xff) ‹‹ 8) |
    			(carpetColors[damage][2] & 0xff);
    }
    /**
     * Determines the damage on the item the block drops. Used in cloth and wood.
     */
    protected int damageDropped(int par1)
    {
        return par1;
    }
    /**
     * Returns true if the block at the coordinates of world passed is a valid a carpet block.
     */
    public static final boolean isCarpetBlockAt(IBlockAccess par0IBlockAccess, int par1, int par2, int par3)
    {
        int var4 = par0IBlockAccess.getBlockId(par1, par2, par3);
        return isCarpetBlock(var4);
    }
    /**
     * Return true if the parameter is a blockID for a carpet block.
     */
    public static final boolean isCarpetBlock(int par0)
    {
        return isCarpetBlock(Block.blocksList[par0]);
    }
    /**
     * Return true if the parameter is a blockID for a carpet block.
     */
    public static final boolean isCarpetBlock(Block par0)
    {
        return par0 != null && par0 instanceof BlockCarpet;
    }
    
    /**
     * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
     * cleared to be reused)
     */
    public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
    {
    	int dir = 0;
    	for(int i = 1; i ‹= 6; i ++) {
    		if(canPlaceBlockAt(par1World, 
    				par2 + RenderBlocks.DV_DIRS[i][0],
    				par3 + RenderBlocks.DV_DIRS[i][1],
    				par4 + RenderBlocks.DV_DIRS[i][2])) {
    			if(dir == 0) dir = i;
    			else {
    				return AxisAlignedBB.getAABBPool().addOrModifyAABBInPool(par2 + 0.0f, par3 + 0.0f, par4 + 0.0f, par2 + 1.0f, par3 + 1.0f, par4 + 1.0f);
    			}
    		}
    	}
    	float xmin = 0.0f, ymin = 0.0f, zmin = 0.0f;
    	float xmax = 1.0f, ymax = 1.0f, zmax = 1.0f;
    	xmin = Math.max(xmin, xmin + RenderBlocks.DV_DIRS[dir][0]);
    	xmax = Math.min(xmax, xmax + RenderBlocks.DV_DIRS[dir][0]);
    	ymin = Math.max(ymin, ymin + RenderBlocks.DV_DIRS[dir][1]);
    	ymax = Math.min(ymax, ymax + RenderBlocks.DV_DIRS[dir][1]);
    	zmin = Math.max(zmin, zmin + RenderBlocks.DV_DIRS[dir][2]);
    	zmax = Math.min(zmax, zmax + RenderBlocks.DV_DIRS[dir][2]);
    	System.out.format("setted up %f, %f, %f, %f, %f, %f\n",
    			xmin, ymin, zmin, xmax, ymax, zmax);
        return AxisAlignedBB.getAABBPool().addOrModifyAABBInPool(par2 + xmin, par3 + ymin, par4 + zmin, par2 + xmax, par3 + ymax, par4 + zmax);
    }
    /**
     * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
     * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
     */
    public boolean isOpaqueCube()
    {
        return false;
    }
    /**
     * Updates the blocks bounds based on its current state. Args: world, x, y, z
     */
    public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    {
    	int dir = 0;
    	for(int i = 1; i ‹= 6; i ++) {
    		if(canPlaceBlockAt(par1IBlockAccess, 
    				par2 + RenderBlocks.DV_DIRS[i][0],
    				par3 + RenderBlocks.DV_DIRS[i][1],
    				par4 + RenderBlocks.DV_DIRS[i][2])) {
    			if(dir == 0) dir = i;
    			else {
    				setBlockBounds(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f);
    				return;
    			}
    		}
    	}
    	float xmin = 0.0f, ymin = 0.0f, zmin = 0.0f;
    	float xmax = 1.0f, ymax = 1.0f, zmax = 1.0f;
    	xmin = Math.max(xmin, xmin + RenderBlocks.DV_DIRS[dir][0]);
    	xmax = Math.min(xmax, xmax + RenderBlocks.DV_DIRS[dir][0]);
    	ymin = Math.max(ymin, ymin + RenderBlocks.DV_DIRS[dir][1]);
    	ymax = Math.min(ymax, ymax + RenderBlocks.DV_DIRS[dir][1]);
    	zmin = Math.max(zmin, zmin + RenderBlocks.DV_DIRS[dir][2]);
    	zmax = Math.min(zmax, zmax + RenderBlocks.DV_DIRS[dir][2]);
    	System.out.format("setted up %f, %f, %f, %f, %f, %f\n",
    			xmin, ymin, zmin, xmax, ymax, zmax);
        setBlockBounds(xmin, ymin, zmin, xmax, ymax, zmax);
    }
    /**
     * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
     */
    public boolean renderAsNormalBlock()
    {
        return false;
    }
    /**
     * The type of render function that is called for this block
     */
    public int getRenderType()
    {
        return 501;
    }
    /**
     * Returns the quantity of items to drop on block destruction.
     */
    public int quantityDropped(Random par1Random)
    {
        return 1;
    }
    /**
     * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
     */
    public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
    {
        return canPlaceBlockAt((IBlockAccess)par1World, par2, par3, par4);
    }
    /**
     * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
     */
    public boolean canPlaceBlockAt(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    {
        return canPlaceOn(par1IBlockAccess.getBlockId(par2, par3 - 1, par4)) ||
        		canPlaceOn(par1IBlockAccess.getBlockId(par2, par3 + 1, par4)) ||
        		canPlaceOn(par1IBlockAccess.getBlockId(par2, par3, par4 - 1)) ||
        		canPlaceOn(par1IBlockAccess.getBlockId(par2, par3, par4 + 1)) ||
        		canPlaceOn(par1IBlockAccess.getBlockId(par2 - 1, par3, par4)) ||
        		canPlaceOn(par1IBlockAccess.getBlockId(par2 + 1, par3, par4));
    }
    
    public static boolean canPlaceOn(Block block) {
    	return block != null && block.isOpaqueCube();
    }
    
    public static boolean canPlaceOn(int blockId) {
    	return canPlaceOn(Block.blocksList[blockId]);
    }
    
    private static int[][] neighboursToCheck = {
    	{ 1, 0, 0 }, { -1, 0, 0 },
    	{ 0, 1, 0 }, { 0, -1, 0 },
    	{ 0, 0, 1 }, { 0, 0, -1 },
    	{ 1, 1, 0 }, { 1, -1, 0 },
    	{ -1, 1, 0 }, { -1, -1, 0 },
    	{ 0, 1, 1 }, { 0, -1, 1 },
    	{ 0, 1, -1 }, { 0, -1, -1 },
    } ;
    /**
     * Called whenever the block is added into the world. Args: world, x, y, z
     */
    public void onBlockAdded(World par1World, int par2, int par3, int par4)
    {
    	setBlockBoundsBasedOnState(par1World, par2, par3, par4);
//    	
//    	for(int i = 0; i ‹ neighboursToCheck.length; i ++) {
//    		if(par1World.getBlockId(par2 + neighboursToCheck[i][0], par3 + neighboursToCheck[i][1], par4 + neighboursToCheck[i][2]) == Block.carpet.blockID)
//    			onNeighborBlockChange(par1World, par2 + neighboursToCheck[i][0], par3 + neighboursToCheck[i][1], par4 + neighboursToCheck[i][2], Block.carpet.blockID);
//    	}
    }
    /**
     * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
     * their own) Args: x, y, z, neighbor blockID
     */
    public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
    {
    	if(!canPlaceBlockAt(par1World, par2, par3, par4)) {
            this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
            par1World.setBlockWithNotify(par2, par3, par4, 0);
    	}
    }
    /**
     * returns a list of blocks with the same ID, but different meta (eg: wood returns 4 blocks)
     */
    public void getSubBlocks(int par1, CreativeTabs par2CreativeTabs, List par3List)
    {
        for (int var4 = 0; var4 ‹ 16; ++var4)
        {
            par3List.add(new ItemStack(par1, 1, var4));
        }
    }
    
    /**
     * Returns an item stack containing a single instance of the current block type. 'i' is the block's subtype/damage
     * and is ignored for blocks which do not support subtypes. Blocks which cannot be harvested should return null.
     */
    protected ItemStack createStackedBlock(int par1)
    {
        return new ItemStack(this.blockID, 1, par1);
    }
    
    /**
     * Ray traces through the blocks collision from start vector to end vector returning a ray trace hit. Args: world,
     * x, y, z, startVec, endVec
     */
    public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3, Vec3 par6Vec3)
    {
        setBlockBoundsBasedOnState(par1World, par2, par3, par4);
        return super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3);
    }
}
 Block.java дополнение
 Block.java дополнение    // ...
    public static final Block carpet = new BlockCarpet(250, 184, 185, 186, true).setHardness(0.1F).setBlockName("carpet").setRequiresSelfNotify();
    public static final Block carpetF = new BlockCarpet(251, 187, 188, 189, false).setHardness(0.1F).setBlockName("carpetF").setRequiresSelfNotify();
    // ...
    static {
        // ...
        Item.itemsList[carpet.blockID] = (new ItemCarpet(carpet.blockID - 256)).setItemName("carpet");
        Item.itemsList[carpetF.blockID] = (new ItemCarpet(carpetF.blockID - 256)).setItemName("carpetF");
    }
    // ...
 CraftingManager.java дополнение
 CraftingManager.java дополнение        for(int i = 0; i ‹ 16; i ++) {
            this.addRecipe(new ItemStack(Item.itemsList[Block.carpet.blockID], 8, i), new Object[] {"##", "##", '#', new ItemStack(Item.itemsList[Block.cloth.blockID], 1, i)});
        }
        this.addRecipe(new ItemStack(Block.carpetF, 8), new Object[] {"##", "##", '#', Block.cloth });
 RenderBlocks.java дополнение
 RenderBlocks.java дополнение    // ...
    /**
     * Renders the block at the given coordinates using the block's rendering type
     */
    public boolean renderBlockByRenderType(Block par1Block, int par2, int par3, int par4)
    {
        int var5 = par1Block.getRenderType();
        par1Block.setBlockBoundsBasedOnState(this.blockAccess, par2, par3, par4);
        // ...
        if(var5 == 501) return renderBlockCarpet((BlockCarpet)par1Block, par2, par3, par4);
        // ...
    }
    // ...
	public static final int DV_ILLEGAL = 0;
	public static final int DV_XPOS = 1;
	public static final int DV_XNEG = 2;
	public static final int DV_YPOS = 3;
	public static final int DV_YNEG = 4;
	public static final int DV_ZPOS = 5;
	public static final int DV_ZNEG = 6;
	public static final int DV_SAME = 0;
	public static final int DV_OPPOSITE = 1;
	public static final int DV_ROTATE_XPOS = 2;
	public static final int DV_ROTATE_XNEG = 3;
	public static final int DV_ROTATE_YPOS = 4;
	public static final int DV_ROTATE_YNEG = 5;
	public static final int DV_ROTATE_ZPOS = 6;
	public static final int DV_ROTATE_ZNEG = 7;
	public static final int[][] DV_TRANSFORMS = {
		{ DV_ILLEGAL, DV_ILLEGAL, DV_ILLEGAL, DV_ILLEGAL, DV_ILLEGAL, DV_ILLEGAL, DV_ILLEGAL, DV_ILLEGAL, },
		{ DV_XPOS, DV_XNEG, DV_XPOS, DV_XPOS, DV_ZNEG, DV_ZPOS, DV_YPOS, DV_YNEG, },
		{ DV_XNEG, DV_XPOS, DV_XNEG, DV_XNEG, DV_ZPOS, DV_ZNEG, DV_YNEG, DV_YPOS, },
		{ DV_YPOS, DV_YNEG, DV_ZPOS, DV_ZNEG, DV_YPOS, DV_YPOS, DV_XNEG, DV_XPOS, },
		{ DV_YNEG, DV_YPOS, DV_ZNEG, DV_ZPOS, DV_YNEG, DV_YNEG, DV_XPOS, DV_XNEG, },
		{ DV_ZPOS, DV_ZNEG, DV_YNEG, DV_YPOS, DV_XPOS, DV_XNEG, DV_ZPOS, DV_ZPOS, },
		{ DV_ZNEG, DV_ZPOS, DV_YPOS, DV_YNEG, DV_XNEG, DV_XPOS, DV_ZNEG, DV_ZNEG, },
	};
	public static final int[][] DV_DIRS = {
		{ 0, 0, 0, },
		{ 1, 0, 0, },
		{ -1, 0, 0, },
		{ 0, 1, 0, },
		{ 0, -1, 0, },
		{ 0, 0, 1, },
		{ 0, 0, -1, },
	};
	private static final int[][][] CORNERS = {
		null,
		{ { 1, 0, 0, }, { 0, 1, 0, }, { 0, 0, 1, }, },
		{ { 0, 0, 0, }, { 0, 0, 1, }, { 0, 1, 0, }, },
		{ { 0, 1, 0, }, { 0, 0, 1, }, { 1, 0, 0, }, },
		{ { 0, 0, 0, }, { 1, 0, 0, }, { 0, 0, 1, }, },
		{ { 0, 0, 1, }, { 1, 0, 0, }, { 0, 1, 0, }, },
		{ { 0, 0, 0, }, { 0, 1, 0, }, { 1, 0, 0, }, },
	};
	private static final int[][] TEXTURES_INSIDE = {
		{ 0, 0, }, { 0, 1, }, { 1, 1, }, { 1, 0, },
	};
	
	private static final int[][] LAY_INSIDE = {
		{ 0, 0, }, { 0, 1, }, { 1, 1, }, { 1, 0, }, 
	};
	
	private static final double[][][] carpet2ndStageTexCoords = {
		{ { 0.0d, 0.0d, }, { 0.0d, 0.25d, }, { 1.0d, 0.25d, }, { 1.0d, 0.0d, }, },
		{ { 1.0d, 0.75d, }, { 0.0d, 0.75d, }, { 0.0d, 1.0d, }, { 1.0d, 1.0d, }, },
		{ { 0.0d, 0.25d, }, { 0.0d, 0.5d, }, { 1.0d, 0.5d, }, { 1.0d, 0.25d, }, },
		{ { 1.0d, 0.5d, }, { 0.0d, 0.5d, }, { 0.0d, 0.75d, }, { 1.0d, 0.75d, }, },
	};
	
	private static final double[][][] carpet2ndStageLayCoords = {
		{ { 0.0d, 0.0d, }, { 0.0d, 0.25d, }, { 1.0d, 0.25d, }, { 1.0d, 0.0d, }, },
		{ { 0.75d, 0.0d, }, { 0.75d, 1.0d, }, { 1.0d, 1.0d, }, { 1.0d, 0.0d, }, },
		{ { 0.0d, 0.75d, }, { 0.0d, 1.0d, }, { 1.0d, 1.0d, }, { 1.0d, 0.75d, }, },
		{ { 0.0d, 0.0d, }, { 0.0d, 1.0d, }, { 0.25d, 1.0d, }, { 0.25d, 0.0d, }, },
	};
	
	private static final double[][][] carpet3rdStageTexCoords = {
		{ { 0.0d, 0.0d, }, { 0.0d, 0.5d, }, { 0.5d, 0.5d, }, { 0.5d, 0.0d, }, },
		{ { 0.5d, 0.0d, }, { 0.5d, 0.5d, }, { 1.0d, 0.5d, }, { 1.0d, 0.0d, }, },
		{ { 0.5d, 0.5d, }, { 0.5d, 1.0d, }, { 1.0d, 1.0d, }, { 1.0d, 0.5d, }, },
		{ { 0.0d, 0.5d, }, { 0.0d, 1.0d, }, { 0.5d, 1.0d, }, { 0.5d, 0.5d, }, },
	};
	
	private static final double[][][] carpet3rdStageLayCoords = {
		{ { 0.0d, 0.0d, }, { 0.0d, 0.5d, }, { 0.5d, 0.5d, }, { 0.5d, 0.0d, }, },
		{ { 0.5d, 0.0d, }, { 0.5d, 0.5d, }, { 1.0d, 0.5d, }, { 1.0d, 0.0d, }, },
		{ { 0.5d, 0.5d, }, { 0.5d, 1.0d, }, { 1.0d, 1.0d, }, { 1.0d, 0.5d, }, },
		{ { 0.0d, 0.5d, }, { 0.0d, 1.0d, }, { 0.5d, 1.0d, }, { 0.5d, 0.5d, }, },
	};
	
	private static final int[][][] DV_IDENTS = new int[3][3][3];
	static {
		for(int i = 1; i ‹= 6; i ++) {
			DV_IDENTS[DV_DIRS[i][0] + 1][DV_DIRS[i][1] + 1][DV_DIRS[i][2] + 1] = i;
		}
	}
	private static final int[] carpet3rdStageData = {
		0, 0, 0, 0, 0,
		535822336, 16769040, 524104, 1605357568, -2107637614,
		-536870908, 56999775, 1772992, 1687355264, -79689729,
		63, 0, 0, -1033680896, 1862277965, -67108646, 1073415303,
		33544704,
	};
	
    private boolean renderBlockCarpet(BlockCarpet carpetBlock, int x, int y, int z) {
    	
    	int metadata = this.blockAccess.getBlockMetadata(x, y, z);
    	int blockId = this.blockAccess.getBlockId(x, y, z);
    	int color = carpetBlock.getRenderColor(metadata);
    	
    	if(metadata ‹ 0 || metadata ›= 16) metadata = 0;
    	
    	double baseTexX = (double) ((carpetBlock.blockIndexInTexture & 0xf) ‹‹ 4) / 256.0d;
    	double baseTexY = (double) (carpetBlock.blockIndexInTexture & ~0xf) / 256.0d;
    	double addTexX = (double) ((carpetBlock.sidesTextureIndex & 0xf) ‹‹ 4) / 256.0d;
    	double addTexY = (double) (carpetBlock.sidesTextureIndex & ~0xf) / 256.0d;
    	double fillTexX = (double) ((carpetBlock.fillTextureIndex & 0xf) ‹‹ 4) / 256.0d;
    	double fillTexY = (double) (carpetBlock.fillTextureIndex & ~0xf) / 256.0d;
    	double textureW = 16.0d / 256.0d;
    	double textureH = 16.0d / 256.0d;
    	
    	double renderHeight = -0.001d;
    	double renderHeight2 = renderHeight * 2.0d;
    	double renderHeight3 = renderHeight * 3.0d;
    	
    	Tessellator tessellator = Tessellator.instance;
    	int brightness = carpetBlock.getMixedBrightnessForBlock(this.blockAccess, x, y, z);
    	tessellator.setBrightness(brightness);
    	tessellator.setColorOpaque_I(color);
		for(int dir = 1; dir ‹= 6; dir ++) {
			
    		if(BlockCarpet.canPlaceOn(this.blockAccess.getBlockId(x + DV_DIRS[dir][0], y + DV_DIRS[dir][1], z + DV_DIRS[dir][2]))) {
			
    			int cx = CORNERS[dir][0][0];
				int cy = CORNERS[dir][0][1];
				int cz = CORNERS[dir][0][2];
				int xx = CORNERS[dir][1][0];
				int xy = CORNERS[dir][1][1];
				int xz = CORNERS[dir][1][2];
				int yx = CORNERS[dir][2][0];
				int yy = CORNERS[dir][2][1];
				int yz = CORNERS[dir][2][2];
				
				// stage 1
				for(int k = 0; k ‹ 4; k ++) {
					tessellator.addVertexWithUV(
							x + cx + xx * LAY_INSIDE[k][0] + yx * LAY_INSIDE[k][1] + DV_DIRS[dir][0] * renderHeight,
							y + cy + xy * LAY_INSIDE[k][0] + yy * LAY_INSIDE[k][1] + DV_DIRS[dir][1] * renderHeight,
							z + cz + xz * LAY_INSIDE[k][0] + yz * LAY_INSIDE[k][1] + DV_DIRS[dir][2] * renderHeight,
							baseTexX + textureW * TEXTURES_INSIDE[k][0], baseTexY + textureH * TEXTURES_INSIDE[k][1]);
				}
				
				// stage 2
				int sidedir = DV_IDENTS[-CORNERS[dir][1][0] + 1][-CORNERS[dir][1][1] + 1][-CORNERS[dir][1][2] + 1];
				for(int side = 0; side ‹ 4; side ++) {
					
					sidedir = DV_TRANSFORMS[sidedir][dir - DV_XPOS + DV_ROTATE_XPOS];
					
					boolean canPlaceNear = BlockCarpet.canPlaceOn(this.blockAccess.getBlockId(x + DV_DIRS[sidedir][0], y + DV_DIRS[sidedir][1], z + DV_DIRS[sidedir][2]));
					boolean canPlaceFar = BlockCarpet.canPlaceOn(this.blockAccess.getBlockId(x + DV_DIRS[sidedir][0] + DV_DIRS[dir][0], y + DV_DIRS[sidedir][1] + DV_DIRS[dir][1], z + DV_DIRS[sidedir][2] + DV_DIRS[dir][2]));
					boolean carpetNear = BlockCarpet.isCarpetBlockAt(this.blockAccess, x + DV_DIRS[sidedir][0], y + DV_DIRS[sidedir][1], z + DV_DIRS[sidedir][2]);
					boolean carpetFar = BlockCarpet.isCarpetBlockAt(this.blockAccess, x + DV_DIRS[sidedir][0] + DV_DIRS[dir][0], y + DV_DIRS[sidedir][1] + DV_DIRS[dir][1], z + DV_DIRS[sidedir][2] + DV_DIRS[dir][2]);
					
					if(canPlaceNear || (carpetNear && canPlaceFar) || carpetFar) {
					
						for(int k = 0; k ‹ 4; k ++) {
							tessellator.addVertexWithUV(
									x + cx + xx * carpet2ndStageLayCoords[side][k][0] + yx * carpet2ndStageLayCoords[side][k][1] + DV_DIRS[dir][0] * renderHeight * 2,
									y + cy + xy * carpet2ndStageLayCoords[side][k][0] + yy * carpet2ndStageLayCoords[side][k][1] + DV_DIRS[dir][1] * renderHeight * 2,
									z + cz + xz * carpet2ndStageLayCoords[side][k][0] + yz * carpet2ndStageLayCoords[side][k][1] + DV_DIRS[dir][2] * renderHeight * 2,
									addTexX + textureW * carpet2ndStageTexCoords[side][k][0], addTexY + textureH * carpet2ndStageTexCoords[side][k][1]);
						}
					}
				}
				
				// stage 3
				int sdir1 = DV_IDENTS[-CORNERS[dir][1][0] + 1][-CORNERS[dir][1][1] + 1][-CORNERS[dir][1][2] + 1];
				for(int side = 0; side ‹ 4; side ++) {
					int sdir2 = DV_TRANSFORMS[sdir1][dir - DV_XPOS + DV_ROTATE_XPOS];
					
					int idx1 = this.blockAccess.getBlockId(x + DV_DIRS[sdir1][0] + DV_DIRS[dir][0], y + DV_DIRS[sdir1][1] + DV_DIRS[dir][1], z + DV_DIRS[sdir1][2] + DV_DIRS[dir][2]);
					int idx2 = this.blockAccess.getBlockId(x + DV_DIRS[sdir1][0], y + DV_DIRS[sdir1][1], z + DV_DIRS[sdir1][2]);
					int idz1 = this.blockAccess.getBlockId(x + DV_DIRS[sdir2][0] + DV_DIRS[dir][0], y + DV_DIRS[sdir2][1] + DV_DIRS[dir][1], z + DV_DIRS[sdir2][2] + DV_DIRS[dir][2]);
					int idz2 = this.blockAccess.getBlockId(x + DV_DIRS[sdir2][0], y + DV_DIRS[sdir2][1], z + DV_DIRS[sdir2][2]);
					int idxz1 = this.blockAccess.getBlockId(x + DV_DIRS[sdir1][0] + DV_DIRS[sdir2][0] + DV_DIRS[dir][0], y + DV_DIRS[sdir1][1] + DV_DIRS[sdir2][1] + DV_DIRS[dir][1], z + DV_DIRS[sdir1][2] + DV_DIRS[sdir2][2] + DV_DIRS[dir][2]);
					int idxz2 = this.blockAccess.getBlockId(x + DV_DIRS[sdir1][0] + DV_DIRS[sdir2][0], y + DV_DIRS[sdir1][1] + DV_DIRS[sdir2][1], z + DV_DIRS[sdir1][2] + DV_DIRS[sdir2][2]);
					
					int i1 = BlockCarpet.isCarpetBlock(idz1) ? 1 : Block.blocksList[idz1] != null && Block.blocksList[idz1].isOpaqueCube() ? 2 : 0;
					int i2 = BlockCarpet.isCarpetBlock(idz2) ? 1 : Block.blocksList[idz2] != null && Block.blocksList[idz2].isOpaqueCube() ? 2 : 0;
					int i3 = BlockCarpet.isCarpetBlock(idx1) ? 1 : Block.blocksList[idx1] != null && Block.blocksList[idx1].isOpaqueCube() ? 2 : 0;
					int i4 = BlockCarpet.isCarpetBlock(idx2) ? 1 : Block.blocksList[idx2] != null && Block.blocksList[idx2].isOpaqueCube() ? 2 : 0;
					int i5 = BlockCarpet.isCarpetBlock(idxz1) ? 1 : Block.blocksList[idxz1] != null && Block.blocksList[idxz1].isOpaqueCube() ? 2 : 0;
					int i6 = BlockCarpet.isCarpetBlock(idxz2) ? 1 : Block.blocksList[idxz2] != null && Block.blocksList[idxz2].isOpaqueCube() ? 2 : 0;
					
					int index = 0;
					index = index * 3 + i1;
					index = index * 3 + i2;
					index = index * 3 + i3;
					index = index * 3 + i4;
					index = index * 3 + i5;
					index = index * 3 + i6;
					
					if((carpet3rdStageData[index ››› 5] & (1 ‹‹ (index & 0x1f))) != 0) {
						
						for(int k = 0; k ‹ 4; k ++) {
							tessellator.addVertexWithUV(
									x + cx + xx * carpet3rdStageLayCoords[side][k][0] + yx * carpet3rdStageLayCoords[side][k][1] + DV_DIRS[dir][0] * renderHeight * 3,
									y + cy + xy * carpet3rdStageLayCoords[side][k][0] + yy * carpet3rdStageLayCoords[side][k][1] + DV_DIRS[dir][1] * renderHeight * 3,
									z + cz + xz * carpet3rdStageLayCoords[side][k][0] + yz * carpet3rdStageLayCoords[side][k][1] + DV_DIRS[dir][2] * renderHeight * 3,
									fillTexX + textureW * carpet3rdStageTexCoords[side][k][0], fillTexY + textureH * carpet3rdStageTexCoords[side][k][1]);
						}
					}
					
					sdir1 = sdir2;
					
				}
			}
		}
		
    	return true;
    }
 ItemCarpet.java целиком
 ItemCarpet.java целикомpackage net.minecraft.src;
public class ItemCarpet extends ItemBlock {
	
    public ItemCarpet(int par1)
    {
        super(par1);
        this.setMaxDamage(0);
        this.setHasSubtypes(((BlockCarpet)Block.blocksList[getBlockID()]).colored);
    }
    /**
     * Gets an icon index based on an item's damage value
     */
    public int getIconFromDamage(int par1)
    {
        return Block.blocksList[getBlockID()].getBlockTextureFromSideAndMetadata(2, BlockCloth.getBlockFromDye(par1));
    }
    
    public int getColorFromDamage(int par1, int par2) {
    	return Block.blocksList[getBlockID()].getRenderColor(par1);
    }
    /**
     * Returns the metadata of the block which this Item (ItemBlock) can place
     */
    public int getMetadata(int par1)
    {
        return par1;
    }
    public String getItemNameIS(ItemStack par1ItemStack)
    {
        return super.getItemName() + (getHasSubtypes() ? "." + ItemDye.dyeColorNames[BlockCloth.getBlockFromDye(par1ItemStack.getItemDamage())] : "");
    }
}
 Программа, которой генерировались данные из массивов
 Программа, которой генерировались данные из массивовimport /* hidden! here should be imports of 3d graphics library */;
import java.util.ArrayList;
public class MainGen {
	public static void main(String[] strs) {
		Vector3d[] d = {
				null,
				Utils.X_AXIS,
				Utils.X_AXIS.opposite(),
				Utils.Y_AXIS,
				Utils.Y_AXIS.opposite(),
				Utils.Z_AXIS,
				Utils.Z_AXIS.opposite(),
		};
		int maxalgos = 0;
		ArrayList‹Vector3d›[] table = new ArrayList[d.length];
		for(int i = 0; i ‹ table.length; i ++) {
			table[i] = new ArrayList‹Vector3d›();
			if(d[i] == null) continue;
			// algo 0: same
			table[i].add(d[i]);
			// algo 1: opposite
			table[i].add(d[i].opposite());
			// algo 2: rotate xp
			table[i].add(Utils.rotate(Utils.X_AXIS, d[i], Math.PI / 2));
			// algo 3: rotate xn
			table[i].add(Utils.rotate(Utils.X_AXIS.opposite(), d[i], Math.PI / 2));
			// algo 4: rotate yp
			table[i].add(Utils.rotate(Utils.Y_AXIS, d[i], Math.PI / 2));
			// algo 5: rotate yn
			table[i].add(Utils.rotate(Utils.Y_AXIS.opposite(), d[i], Math.PI / 2));
			// algo 6: rotate zp
			table[i].add(Utils.rotate(Utils.Z_AXIS, d[i], Math.PI / 2));
			// algo 7: rotate zn
			table[i].add(Utils.rotate(Utils.Z_AXIS.opposite(), d[i], Math.PI / 2));
			// finish
			maxalgos = Math.max(maxalgos, table[i].size());
		}
		
		// now generate Java code
		System.out.println("/** GENERATED CODE: DO NOT MODIFY */");
		String[] equivs = {
			"ILLEGAL",
			"XPOS",
			"XNEG",
			"YPOS",
			"YNEG",
			"ZPOS",
			"ZNEG",
		};
		String[] ops = {
			"SAME",
			"OPPOSITE",
			"ROTATE_XPOS",
			"ROTATE_XNEG",
			"ROTATE_YPOS",
			"ROTATE_YNEG",
			"ROTATE_ZPOS",
			"ROTATE_ZNEG",
		};
		for(String s : equivs) {
			System.out.format("\tprivate static final int DV_%s = %d;\n", s, find(s, equivs));
		}
		System.out.println();
		for(String s : ops) {
			System.out.format("\tprivate static final int DV_%s = %d;\n", s, find(s, ops));
		}
		System.out.println();
		System.out.println("\tprivate static final int[][] DV_TRANSFORMS = {");
		for(int k = 0; k ‹ table.length; k ++) {
			ArrayList‹Vector3d› l = table[k];
			System.out.print("\t\t{");
			for(Vector3d v : l) {
				int found = find(v, d);
				System.out.format(" DV_%s,", equivs[found ‹ 0 ? 0 : found]);
			}
			for(int i = l.size(); i ‹ maxalgos; i ++) {
				System.out.format(" DV_%s,", equivs[0]);
			}
			System.out.println(" },");
		}
		System.out.println("\t};");
		System.out.println();
		System.out.println("\tprivate static final int[][] DV_DIRS = {");
		for(Vector3d v : d) {
			System.out.format("\t\t{ %d, %d, %d, },\n",
					(int)Math.round(v == null ? 0.0d : v.getXLength()),
					(int)Math.round(v == null ? 0.0d : v.getYLength()),
					(int)Math.round(v == null ? 0.0d : v.getZLength()));
		}
		System.out.println("\t};");
		System.out.println();
		// now generate corners
		System.out.println();
		System.out.println("\tprivate static final int[][][] CORNERS_INSIDE = {");
		System.out.println("\t\tnull,");
		Point3d pz = Utils.ZERO_ORIGIN;
		Point3d po = new Point3d(1.0d, 1.0d, 1.0d);
		for(int i = 1; i ‹ d.length; i ++) {
			Vector3d dir = d[i];
			Point3d v = new Point3d(0.5d, 0.5d, 0.5d);
			Plane3d p = dir.perpendicular(v.translate(dir.product(0.5d)));
			Point3d p1 = Utils.projection(p, pz);
			Point3d p3 = Utils.projection(p, po);
			Point3d pc = p1.translate(p1.fromTo(p3).product(0.5d));
			Ray3d ray = new Ray3d(pc, dir);
			Point3d p2 = Utils.rotate(ray, p1, Math.PI / 2);
			Point3d p4 = Utils.rotate(ray, p3, Math.PI / 2);
			System.out.format("\t\t{ { %d, %d, %d, }, { %d, %d, %d, }, { %d, %d, %d, }, { %d, %d, %d, }, },\n",
					(int)Math.round(p1.getX()), (int)Math.round(p1.getY()), (int)Math.round(p1.getZ()),
					(int)Math.round(p4.getX()), (int)Math.round(p4.getY()), (int)Math.round(p4.getZ()),
					(int)Math.round(p3.getX()), (int)Math.round(p3.getY()), (int)Math.round(p3.getZ()),
					(int)Math.round(p2.getX()), (int)Math.round(p2.getY()), (int)Math.round(p2.getZ()));
		}
		System.out.println("\t};");
		System.out.println();
		// now generate corners
		System.out.println();
		System.out.println("\tprivate static final int[][][] CORNERS = {");
		System.out.println("\t\tnull,");
		for(int i = 1; i ‹ d.length; i ++) {
			Vector3d dir = d[i];
			Point3d v = new Point3d(0.5d, 0.5d, 0.5d);
			Plane3d p = dir.perpendicular(v.translate(dir.product(0.5d)));
			Point3d p1 = Utils.projection(p, pz);
			Point3d p3 = Utils.projection(p, po);
			Point3d pc = p1.translate(p1.fromTo(p3).product(0.5d));
			Ray3d ray = new Ray3d(pc, dir);
			Point3d p2 = Utils.rotate(ray, p1, Math.PI / 2);
			Point3d p4 = Utils.rotate(ray, p3, Math.PI / 2);
			System.out.format("\t\t{ { %d, %d, %d, }, { %d, %d, %d, }, { %d, %d, %d, }, },\n",
					(int)Math.round(p1.getX()), (int)Math.round(p1.getY()), (int)Math.round(p1.getZ()),
					(int)Math.round(p2.getX() - p1.getX()), (int)Math.round(p2.getY() - p1.getY()), (int)Math.round(p2.getZ() - p1.getZ()),
					(int)Math.round(p3.getX() - p2.getX()), (int)Math.round(p3.getY() - p2.getY()), (int)Math.round(p3.getZ() - p2.getZ()));
		}
		System.out.println("\t};");
		System.out.println();
		// generating carpetDvSides
		System.out.println("\tprivate static final int[][] carpetDvSides = {");
		System.out.println("\t\tnull,");
		for(int i = 1; i ‹ d.length; i ++) {
			Vector3d dir = d[i];
			Point3d v = new Point3d(0.5d, 0.5d, 0.5d);
			Plane3d p = dir.perpendicular(v.translate(dir.product(0.5d)));
			Point3d p1 = Utils.projection(p, pz);
			Point3d p3 = Utils.projection(p, po);
			Point3d pc = p1.translate(p1.fromTo(p3).product(0.5d));
			Ray3d ray = new Ray3d(pc, dir);
			Point3d p2 = Utils.rotate(ray, p1, Math.PI / 2);
			Point3d p4 = Utils.rotate(ray, p3, Math.PI / 2);
			System.out.format("\t\t{ DV_%s, DV_%s, DV_%s, DV_%s, },\n",
					equivs[find(Utils.rotate(dir, Utils.fromTo(p1, p4), Math.PI / 2), d)],
					equivs[find(Utils.rotate(dir, Utils.fromTo(p4, p3), Math.PI / 2), d)],
					equivs[find(Utils.rotate(dir, Utils.fromTo(p3, p2), Math.PI / 2), d)],
					equivs[find(Utils.rotate(dir, Utils.fromTo(p2, p1), Math.PI / 2), d)]
				);
		}
		System.out.println("\t};");
		System.out.println();
		// generating carpet3rdStageFlags
		int other = 0;
		int carpet = 1;
		int block = 2;
		int[][][] space = {
				{
					{ block, block, block, block, },
					{ block, block, block, block, },
					{ block, block, block, block, },
					{ block, block, block, block, },
				},
				{
					{ block, block, block, block, },
					{ block, block, other, block, },
					{ block, carpet, other, block, },
					{ block, block, block, block, },
				},
				{
					{ block, block, block, block, },
					{ block, other, other, block, },
					{ block, other, other, block, },
					{ block, block, block, block, },
				},
				{
					{ block, block, block, block, },
					{ block, block, block, block, },
					{ block, block, block, block, },
					{ block, block, block, block, },
				},
		};
		int[] data = new int[23];
		for(int i1 = 0; i1 ‹ 3; i1 ++)
			for(int i2 = 0; i2 ‹ 3; i2 ++)
				for(int i3 = 0; i3 ‹ 3; i3 ++)
					for(int i4 = 0; i4 ‹ 3; i4 ++)
						for(int i5 = 0; i5 ‹ 3; i5 ++)
							for(int i6 = 0; i6 ‹ 3; i6 ++) {
								space[1][1][2] = i1;
								space[1][2][2] = i2;
								space[2][1][1] = i3;
								space[2][2][1] = i4;
								space[2][1][2] = i5;
								space[2][2][2] = i6;
								int perp = DV_YPOS;
								int dir = DV_ZPOS;
								int xc = 1;
								int yc = 2;
								int zc = 1;
								for(;;) {
									int next = space[xc + DV_DIRS[dir][0]][yc + DV_DIRS[dir][1]][zc + DV_DIRS[dir][2]];
									if(next == block) {
										int nperp = DV_TRANSFORMS[dir][DV_OPPOSITE];
										dir = DV_TRANSFORMS[dir][perp - DV_XPOS + DV_ROTATE_XPOS];
										perp = nperp;
										// System.out.print("nblock");
									} else {
										next = space[xc + DV_DIRS[dir][0] + DV_DIRS[DV_TRANSFORMS[perp][DV_OPPOSITE]][0]]
												[yc + DV_DIRS[dir][1] + DV_DIRS[DV_TRANSFORMS[perp][DV_OPPOSITE]][1]]
												[zc + DV_DIRS[dir][2] + DV_DIRS[DV_TRANSFORMS[perp][DV_OPPOSITE]][2]];
										if(next == block) {
											xc += DV_DIRS[dir][0];
											yc += DV_DIRS[dir][1];
											zc += DV_DIRS[dir][2];
											dir = DV_TRANSFORMS[dir][perp - DV_XPOS + DV_ROTATE_XPOS];
											// System.out.print("nfree");
										} else {
											xc += DV_DIRS[dir][0] + DV_DIRS[DV_TRANSFORMS[perp][DV_OPPOSITE]][0];
											yc += DV_DIRS[dir][1] + DV_DIRS[DV_TRANSFORMS[perp][DV_OPPOSITE]][1];
											zc += DV_DIRS[dir][2] + DV_DIRS[DV_TRANSFORMS[perp][DV_OPPOSITE]][2];
											int ndir = DV_TRANSFORMS[dir][perp - DV_XPOS + DV_ROTATE_XPOS];
											perp = dir;
											dir = ndir;
											// System.out.print("nfree2");
										}
									}
									if(perp == DV_TRANSFORMS[dir][DV_OPPOSITE]) throw new IllegalArgumentException();
									// System.out.println(" " + xc + " " + yc + " " + zc + " " + dir + " " + perp);
									if(xc == 1 && yc == 2 && zc == 1 && perp == DV_YPOS && dir == DV_ZPOS) {
										int index = 0;
										index = index * 3 + i1;
										index = index * 3 + i2;
										index = index * 3 + i3;
										index = index * 3 + i4;
										index = index * 3 + i5;
										index = index * 3 + i6;
										data[index ››› 5] |= 1 ‹‹ (index & 0x1f);
										break;
									}
									if(space[xc][yc][zc] != carpet) break;
								}
								if(xc == 1 && yc == 2 && zc == 1 && perp == DV_YPOS && dir == DV_ZPOS) {
								}
								// System.out.println();
							}
		System.out.println("\tprivate static final int[] carpet3rdStageData = {");
		System.out.print("\t\t");
		for(int i = 0; i ‹ data.length; i ++) {
			System.out.print(data[i] + ", ");
		}
		System.out.println();
		System.out.println("\t};\n");
	}
		
	public static final int DV_ILLEGAL = 0;
	public static final int DV_XPOS = 1;
	public static final int DV_XNEG = 2;
	public static final int DV_YPOS = 3;
	public static final int DV_YNEG = 4;
	public static final int DV_ZPOS = 5;
	public static final int DV_ZNEG = 6;
	public static final int DV_SAME = 0;
	public static final int DV_OPPOSITE = 1;
	public static final int DV_ROTATE_XPOS = 2;
	public static final int DV_ROTATE_XNEG = 3;
	public static final int DV_ROTATE_YPOS = 4;
	public static final int DV_ROTATE_YNEG = 5;
	public static final int DV_ROTATE_ZPOS = 6;
	public static final int DV_ROTATE_ZNEG = 7;
	public static final int[][] DV_TRANSFORMS = {
		{ DV_ILLEGAL, DV_ILLEGAL, DV_ILLEGAL, DV_ILLEGAL, DV_ILLEGAL, DV_ILLEGAL, DV_ILLEGAL, DV_ILLEGAL, },
		{ DV_XPOS, DV_XNEG, DV_XPOS, DV_XPOS, DV_ZNEG, DV_ZPOS, DV_YPOS, DV_YNEG, },
		{ DV_XNEG, DV_XPOS, DV_XNEG, DV_XNEG, DV_ZPOS, DV_ZNEG, DV_YNEG, DV_YPOS, },
		{ DV_YPOS, DV_YNEG, DV_ZPOS, DV_ZNEG, DV_YPOS, DV_YPOS, DV_XNEG, DV_XPOS, },
		{ DV_YNEG, DV_YPOS, DV_ZNEG, DV_ZPOS, DV_YNEG, DV_YNEG, DV_XPOS, DV_XNEG, },
		{ DV_ZPOS, DV_ZNEG, DV_YNEG, DV_YPOS, DV_XPOS, DV_XNEG, DV_ZPOS, DV_ZPOS, },
		{ DV_ZNEG, DV_ZPOS, DV_YPOS, DV_YNEG, DV_XNEG, DV_XPOS, DV_ZNEG, DV_ZNEG, },
	};
	
	public static final int[][] DV_DIRS = {
		{ 0, 0, 0, },
		{ 1, 0, 0, },
		{ -1, 0, 0, },
		{ 0, 1, 0, },
		{ 0, -1, 0, },
		{ 0, 0, 1, },
		{ 0, 0, -1, },
	};
	private static int find(Object obj, Object[] arr) {
		for(int i = 0; i ‹ arr.length; i ++)
			if(arr[i] == null ? obj == null : arr[i].equals(obj))
				return i;
		return -1;
	}
}
 Достижения
 Достижения Биржа
 Биржа 
 Карты ↓
 Карты ↓



 Поиск
 Поиск Твинки
 Твинки Друзья
 Друзья Администрация
 Администрация