[1,7.10][Генерация]Удобная послойная генерация

5,018
47
783
Привет всем! Решил рассказать об очень удобной послойной генерации, о коей поведал мне timaxa007
Берете, создаете свой генератор(регистрируете, туда сюда)
После чего в свой генератор пишете вот это. Каждый из этих эл.массива как бы вид сверху. В данном коде
0-Воздух
1-Дерево
2-Листва
И вообще, очень гибко, вы можете писать хоть 3, 4, 5 ... 1000, сколько угодно, пока позволяет Integer.Главное писать условия, что вы хотите ставить на место 3, 4, 5 ... 1000.
Код:
public class TreeOsinaGen extends WorldGenerator {

 int[][][] structural_layers = new int[][][] {
 {
 {0, 0, 0, 0, 0},
 {0, 0, 0, 0, 0},
 {0, 0, 1, 0, 0},
 {0, 0, 0, 0, 0},
 {0, 0, 0, 0, 0}
 },{
 {0, 0, 0, 0, 0},
 {0, 0, 0, 0, 0},
 {0, 0, 1, 0, 0},
 {0, 0, 0, 0, 0},
 {0, 0, 0, 0, 0}
 },{
 {0, 0, 0, 0, 0},
 {0, 0, 0, 0, 0},
 {0, 0, 1, 0, 0},
 {0, 0, 0, 0, 0},
 {0, 0, 0, 0, 0}
 },{
 {0, 0, 0, 0, 0},
 {0, 0, 0, 0, 0},
 {0, 0, 1, 0, 0},
 {0, 0, 0, 0, 0},
 {0, 0, 0, 0, 0}
 },{
 {0, 0, 0, 0, 0},
 {0, 2, 2, 2, 0},
 {0, 2, 1, 2, 0},
 {0, 2, 2, 2, 0},
 {0, 0, 0, 0, 0}
 },{
 {0, 0, 0, 0, 0},
 {0, 2, 2, 2, 0},
 {0, 2, 1, 2, 0},
 {0, 2, 2, 2, 0},
 {0, 0, 0, 0, 0}
 },{
 {0, 0, 0, 0, 0},
 {0, 0, 2, 0, 0},
 {0, 2, 1, 2, 0},
 {0, 0, 2, 0, 0},
 {0, 0, 0, 0, 0}
 },{
 {0, 0, 0, 0, 0},
 {0, 0, 2, 0, 0},
 {0, 2, 1, 2, 0},
 {0, 0, 2, 0, 0},
 {0, 0, 0, 0, 0}
 },{
 {0, 0, 0, 0, 0},
 {0, 0, 0, 0, 0},
 {0, 0, 2, 0, 0},
 {0, 0, 0, 0, 0},
 {0, 0, 0, 0, 0}
 }
 };

 @Override
 public boolean generate(World world, Random random, int x, int y, int z) {
 for (int py = 0; py < structural_layers.length; ++py) {
 for (int px = 0; px < structural_layers[py].length; ++px) {
 for (int pz = 0; pz < structural_layers[py][px].length; ++pz) {

 int px2 = px - ((structural_layers[py].length / 2));
 int pz2 = pz - ((structural_layers[py][px].length / 2));
 if (structural_layers[py][px][pz] != 0 &&
 (structural_layers[py][px][pz] == 1 || world.getBlock(x + px2, y + py, z + pz2).isReplaceable(world, x + px2, y + py, z + pz2))) {
    world.setBlock(x + px2, y + py, z + pz2,   structural_layers[py][px][pz] == 1 ? MyBlocks.treeOsina : MyBlocks.osinaLeaves,structural_layers[py][px][pz] == 1 ? 0 : 0, 3);
 }

 }
 }
 }
 return true;
 }

}
Еще, после запятой можно указать метадату, если таковая имеется у вашего блока
Код:
structural_layers[py][px][pz] == 1 ? 0 : 0, 3

Тут генерируется дерево. Но вы можете таким же макаром генерить все что угодно. Очевидно, что это очень удобно для данжей и мегаструктур.
 

timaxa007

Модератор
5,831
409
672
Можно даже написать:
Код:
byte[][][] structural_layers = new byte[][][] {
		{
			{1}
		},{
			{1}
		},{
			{1}
		},{
			{1}
		},{
			{2, 2, 2},
			{2, 1, 2},
			{2, 2, 2}
		},{
			{2, 2, 2},
			{2, 1, 2},
			{2, 2, 2}
		},{
			{0, 2, 0},
			{2, 1, 2},
			{0, 2, 0}
		},{
			{0, 2, 0},
			{2, 1, 2},
			{0, 2, 0}
		},{
			{2}
		}
};
structural_layers желательно использовать модификатор static, но это зависит от вас, как вы его будете применять.
 
5,018
47
783
Даже быстрее, я думаю.
 
2,505
81
397
>>Еще, после запятой можно указать метадату, если таковая имеется у вашего блока
Вообще-то не после запятой, а вместо этого бесполезного выражения structural_layers[py][px][pz] == 1 ? 0 : 0
 
5,018
47
783
>>Это же итак очевидно
Не все такие прозорливые суперпуперпрограммисты как ты. Хорош уже.
 
2,505
81
397
Maxik001 написал(а):
>>Это же итак очевидно
Не все такие прозорливые суперпуперпрограммисты как ты. Хорош уже.

Я там накосячил сам :)) Я отредактировал
 

timaxa007

Модератор
5,831
409
672
В этом коде я использовал switch.
Код:
public class WorldGenTree extends WorldGenerator {

	static byte[][][] structural_layers = new byte[][][]{
		{
			{0, 0, 0},
			{0, 1, 0},
			{0, 0, 0}
		},{
			{0, 0, 0},
			{0, 1, 0},
			{0, 0, 0}
		},{
			{0, 0, 0},
			{0, 1, 0},
			{0, 0, 0}
		},{
			{2, 2, 2},
			{2, 1, 2},
			{2, 2, 2}
		},{
			{0, 2, 0},
			{2, 1, 2},
			{0, 2, 0}
		},{
			{0, 0, 0},
			{0, 2, 0},
			{0, 0, 0}
		}
	};

//Длина первого массива - это высота постройки.
//Длина второго и третьего - это ширина и длина постройки и длина второго и третьего массива должна быть не чётной, дабы аргументы координат, указанные в методе generate, были центром постройки.

	@Override
	public boolean generate(World world, Random random, int x, int y, int z) {
		//Тройной массив пропускаем по трём циклам.
		for (int py = 0; py < structural_layers.length; ++py) {
		for (int px = 0; px < structural_layers[py].length; ++px) {
		for (int pz = 0; pz < structural_layers[py][px].length; ++pz) {

			//Смещение для центровки x и z координат.
			int px2 = px - (structural_layers[py].length / 2);
			int pz2 = pz - (structural_layers[py][px].length / 2);

			switch(structural_layers[py][px][pz]){
			case 1:
				//Поставиться блок, если даже стоял какой-либо другой блок.
				world.setBlock(x + px2, y + py, z + pz2, Mod.block_log, 1, 3);
				break;
			case 2:
				//Если на данной координате будет блок с материалом isReplaceable ...
				if (world.getBlock(x + px2, y + py, z + pz2).isReplaceable(world, x + px2, y + py, z + pz2)) {
					//то будет поставлен блок.
					world.setBlock(x + px2, y + py, z + pz2, Mod.block_leaves, 1, 3);
				}
				break;
			//Любые другие значения (тот-же '0') будут пропускать свой цикл (и ни чего делать в мире).
			default:continue;
			}

		}
		}
		}
		return true;
	}

}
Mod.block_log - объект блок ствола дерева.
Mod.block_leaves - объект блок листвы дерева.

По "case 1": Саженец оказался с материалом не isReplaceable. А кто мешает поставить свою проверку или дополнительный case.
Можно и так написать:
Код:
	static byte[][][] structural_layers = new byte[][][]{
		{
			{0, 0, 0, 0, 0},
			{0, 0, 0, 0, 0},
			{0, 0, 1, 0, 0},
			{0, 0, 0, 0, 0},
			{0, 0, 0, 0, 0}
		},{
			{0, 0, 0, 0, 0},
			{0, 0, 0, 0, 0},
			{0, 0, 1, 0, 0},
			{0, 0, 0, 0, 0},
			{0, 0, 0, 0, 0}
		},{
			{0, 0, 0, 0, 0},
			{0, 0, 0, 0, 0},
			{0, 0, 1, 0, 0},
			{0, 0, 0, 0, 0},
			{0, 0, 0, 0, 0}
		},{
			{0, 0, 0, 0, 0},
			{0, 2, 2, 2, 0},
			{0, 2, 1, 2, 0},
			{0, 2, 2, 2, 0},
			{0, 0, 0, 0, 0}
		},{
			{0, 0, 0, 0, 0},
			{0, 0, 2, 0, 0},
			{0, 2, 1, 2, 0},
			{0, 0, 2, 0, 0},
			{0, 0, 0, 0, 0}
		},{
			{0, 0, 0, 0, 0},
			{0, 0, 0, 0, 0},
			{0, 0, 2, 0, 0},
			{0, 0, 0, 0, 0},
			{0, 0, 0, 0, 0}
		}
	};
Можно и так:
Код:
	static byte[][][] structural_layers = new byte[][][]{
		{
			{1}
		},{
			{1}
		},{
			{1}
		},{
			{2, 2, 2},
			{2, 1, 2},
			{2, 2, 2}
		},{
			{0, 2, 0},
			{2, 1, 2},
			{0, 2, 0}
		},{
			{2}
		}
	};
Проверял через саженец и через генератор.

Вызывать это код можно примерно так:
Код:
new WorldGenTree().generate(world, random, x, y, z);
world - объект World.
random - объект Random, можно взять этот объект из world.rand.
x, y, z - тип int.
 
2,505
81
397
Очень удобный метод генерации, хоть и слишком очевидный.

Мне потом пригодится. Поэтому я запилил еще удобнее  :)

Код:
public abstract class MultiLayerGeneration extends WorldGenerator
{
    /**
     * Можно забыть и не думать, что тут :)
     */
    @Override
    public boolean generate(World world, Random random, int x, int y, int z)
    {
        byte[][][] matrix = get3LayerMatrix();
        for (int py = 0; py < matrix.length; ++py) {
            for (int px = 0; px < matrix[py].length; ++px) {
                for (int pz = 0; pz < matrix[py][px].length; ++pz) {
                    int px2 = px, py2 = py, pz2 = pz;
                    if (needCentering()) {
                        px2 -= matrix[py].length / 2;
                        pz2 -= matrix[py][px].length / 2;
                    }
                    generateBlock(world, random, px2, py2, pz2, matrix[py][px][pz]);
                }
            }
        }
        return true;
    }

    /**
     * @param x, y, z - позиция блока
     * @param matrixValue - значение матрицы для этого блока
     * @return
     */
    protected abstract void generateBlock(World world, Random random, int x, int y, int z, int matrixValue);

    /**
     * Возвращает трехмерную матрицу матрицу.
     */
    protected abstract byte[][][] get3LayerMatrix();

    /**
     * @return true, если нужна центровка
     */
    protected boolean needCentering()
    {
        return true;
    }
}

И затем юзверям(нам) останется только определить эти абстрактые методы.
Код:
public class TestMLG extends MultiLayerGeneration
{
    static final byte[][][] MATRIX = new byte[][][] {
        {
            {0, 0, 0},
            {0, 1, 0},
            {0, 0, 0}
        },{
            {0, 0, 0},
            {0, 1, 0},
            {0, 0, 0}
        },{
            {0, 0, 0},
            {0, 1, 0},
            {0, 0, 0}
        },{
            {2, 2, 2},
            {2, 1, 2},
            {2, 2, 2}
        },{
            {0, 2, 0},
            {2, 1, 2},
            {0, 2, 0}
        },{
            {0, 0, 0},
            {0, 2, 0},
            {0, 0, 0}
        }
    };

    @Override
    protected byte[][][] get3LayerMatrix()
    {
        return MATRIX;
    }

    @Override
    protected void generateBlock(World world, Random random, int x, int y, int z, int matrixValue)
    {
        switch(matrixValue) {
        case 1:
            //Поставиться блок, если даже стоял какой-либо другой блок.
            world.setBlock(x, y, z, какой_нибудьБлок1, 1, 3);
            break;
        case 2:
            //Если на данной координате будет блок с материалом isReplaceable ...
            if (world.getBlock(x, y, z).isReplaceable(world, x, y, z)) {
                //то будет поставлен блок.
                world.setBlock(x, y, z, какой_нибудьБлок1, 1, 3);
            }
            break;
        //Любые другие значения (тот-же '0') будут пропускать свой цикл (и ни чего делать в мире).
        }
    }
}
 
5,018
47
783
Проапгредил тимахин код.
 
2,505
81
397
Maxik001 написал(а):
Проапгредил тимахин код.

Ну а почему нет? Просто постоянно копипастить это цикл - очень неудобно. И свич внутри него некрасивый.


И про смещения забыть можно
 
Сверху