Хочу ковер, который соединяется по краям и по углам с соседними коврами, пригодится для декораций. Его можно вешать на стену, на потолок, слать по углам.
Уже сделаны 3 стадии прорисовки:
1. Собственно, ковер.
2. Соединение с соседними коврами по краям.
3. Соединение с соседними коврами по углам.
Теперь надо добавить ambient occlusion.
Первая стадия
Вторая стадия
Третья стадия
Теперь цветной
ДА!!! Это то, чего вы так долго ждали!
Без коментариев
Сделал текстурку поколоритнее, цвета можно комбинировать:
Ковры соединяются с собой в бесконечном количестве, т.е. вы сможете постелить дома здоровенный ковер 5х5 или постелить длиннющий вдоль дорожки 20х2 к вашему гробу. Или обстелить весь гроб к черту, хоть какое-то разнообразие будет.
Ловушку с помощью ковра не сделать, потому что ковер стелится там, где есть блок.
Даже не знаю как быть со ступеньками, полублоками и косыми блоками. Надо будет что-то придумать.
Крафты
Код в настоящий момент. НЕ последняя версия, просто для ознакомления
Лицензия WTFPL.
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 дополнение
// ...
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 дополнение
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 дополнение
// ...
/**
* 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 целиком
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;
}
}