Генерация биомов (часть 1)

Генерация биомов (часть 1)

Нет прав для скачивания
Версия(и) Minecraft
1.12.2
Содержание

Предисловие
К данному руководству прикреплены исходники, а также картинки и массивы всех использованных слоев GenLayer. В руководстве для описания слоев GenLayer использовалось 3 разных чанка из Обычного мира (без добавления новых биомов), на которых сгенерировались столовые горы, грибной остров и подсолнечное поле. Сиды и координаты чанков можно найти в папках.

Оглавление

  • Генерация биомов в мире (часть 1) - в данном разделе я постараюсь наиболее наглядно и понятно объяснить по какому принципу работает генератор биомов.
  • Собственный биом - в данном разделе я расскажу, как добавить генерацию биома (Лазуритовая земля), который будет обладать небольшой холмистой границей (Окраина лазуритовой земли) и иметь редкую вариацию (Лазуритовая долина).
1 Генерация биомов в мире (часть 1)

1.1 GenLayer
Биомы генерируются с помощью различных слоев GenLayer – подклассов, которые генерируют массив псевдослучайных чисел в зависимости от их родителя. Исключениями являются слой GenLayerIsland, который генерирует массив не имея родителя, и GenLayerHills, который имеет два родителя. Метод GenLayer.getInts(…) возвращает массив целых чисел, сгенерированных слоем. Они могут быть интерпретированы как океаны или поверхности, температуры или осадки, идентификаторы биомов или же просто как какие-то определенные значения, которые пригодятся в будущем. Это зависит от конкретного подкласса GenLayer.

GenlayerIsland – возвращает массив нулей и единиц. Пока в массиве нет идентификаторов биомов можно считать, что: 0 – это океан, 1 – теплый биом (но до распределения по типам биомов данная цифра обозначает поверхность), 2 – умеренный биом, 3 – холодный биом, 4 – снежный биом.

Пример генерации в виде массива и в виде картинки.
1_GenLayerIsland.png
\[ \begin{bmatrix}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&0&0\\0&0&0&0&0&0&0&0&0\\0&1&0&1&0&0&0&0&0\\0&0&1&1&0&0&0&0&0\\0&1&0&0&0&0&1&0&0\\0&0&0&0&1&0&0&0&0\\1&0&0&0&0&0&0&0&0\\\end{bmatrix} \]

GenLayerFuzzyZoom – увеличивает масштаб области.
1_GenLayerIsland.png

2_GenLayerFuzzyZoom.png
\begin{bmatrix}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&0&0\\0&0&0&0&0&0&0&0&0\\0&1&0&1&0&0&0&0&0\\0&0&1&1&0&0&0&0&0\\0&1&0&0&0&0&1&0&0\\0&0&0&0&1&0&0&0&0\\1&0&0&0&0&0&0&0&0\\\end{bmatrix}\begin{bmatrix}0&0&0&0&0&0&0&0&0&0&0&0&0&0\\0&0&0&0&0&0&0&0&0&0&0&0&0&0\\0&0&0&0&0&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&1&0&0&0&0&0&0&0&0&0&0&0\\0&1&1&0&0&0&1&1&0&0&0&0&0&0\\0&0&0&1&0&0&1&1&0&0&0&0&0&0\\0&0&0&0&1&1&1&1&0&0&0&0&0&0\\0&0&0&1&0&1&1&0&0&0&0&0&1&1\\0&0&1&0&0&0&0&0&0&0&0&0&1&1\\0&0&0&0&0&0&0&0&0&0&0&0&1&0\\0&0&0&0&0&0&0&0&1&0&0&0&0&0\\1&1&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\\\end{bmatrix}
GenLayerZoom – увеличивает масштаб области, но на границах различающихся чисел предпочтение отдается большинству.
1_GenLayerIsland.png

123.png
\begin{bmatrix}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&0&0\\0&0&0&0&0&0&0&0&0\\0&1&0&1&0&0&0&0&0\\0&0&1&1&0&0&0&0&0\\0&1&0&0&0&0&1&0&0\\0&0&0&0&1&0&0&0&0\\1&0&0&0&0&0&0&0&0\\\end{bmatrix}\begin{bmatrix}0&0&0&0&0&0&0&0&0&0&0&0&0&0\\0&0&0&0&0&0&0&0&0&0&0&0&0&0\\0&0&0&0&0&0&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&1&1&0&0&0&1&1&0&0&0&0&0&0\\0&0&0&1&0&1&1&1&0&0&0&0&0&0\\0&0&0&0&1&1&1&1&0&0&0&0&0&0\\0&0&0&1&0&1&1&0&0&0&0&0&1&0\\0&0&1&0&0&0&0&0&0&0&0&0&1&1\\0&0&0&0&0&0&0&0&0&0&0&0&1&0\\0&0&0&0&0&0&0&0&1&0&0&0&0&0\\1&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\\\end{bmatrix}
GenLayerAddIsland – рядом с поверхностью и океаном добавляет дополнительную поверхность. Всегда копирует снежные биомы и с высоким шансом копирует умеренный и холодный биомы.

Пример использования данного слоя три раза подряд.
4_GenLayerZoom.png

5_GenLayerAddIsland.png


7_GenLayerAddIsland.png
\begin{bmatrix}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&1&1&0&0&0&0&0&0&0&0&0&0&0&0&0&0&0&0&0&0\\1&1&1&0&0&0&0&1&0&0&0&0&0&0&0&0&0&0&0&0&0\\1&1&1&1&0&0&0&1&1&1&1&1&1&0&0&0&0&0&0&0&0\\1&1&1&1&0&0&0&0&1&1&1&1&1&0&0&0&0&0&0&0&0\\1&1&1&0&0&0&0&0&1&1&1&1&0&0&0&0&0&0&0&0&0\\1&0&1&1&0&0&0&0&0&1&1&1&1&1&0&0&0&0&0&0&0\\1&0&0&1&0&0&0&0&0&0&0&1&1&1&0&0&0&0&0&0&0\\0&0&0&0&1&0&0&0&0&0&0&1&1&1&0&0&0&0&0&0&0\\1&1&0&0&1&1&0&0&0&0&0&1&1&1&1&0&0&0&1&1&0\\0&1&1&1&0&1&0&0&0&1&1&1&1&0&0&0&0&0&0&1&1\\0&0&0&1&0&0&0&0&1&1&1&1&1&0&0&0&0&0&0&1&1\\0&0&1&1&0&0&0&0&0&1&1&1&0&0&0&0&0&0&0&0&1\\1&1&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&1&0&0&0&1&0&0&0&0&0\\1&0&0&0&0&0&0&0&0&0&0&0&0&0&1&1&0&0&0&0&1\\0&0&0&0&0&0&0&0&0&0&0&0&0&0&0&1&0&0&0&1&1\\0&0&0&0&0&0&0&0&0&0&0&0&1&1&1&0&0&0&1&1&1\\0&0&0&0&0&0&0&0&0&0&0&0&0&1&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\\\end{bmatrix}\begin{bmatrix}0&1&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\\1&0&0&0&0&0&0&0&1&0&0&1&0&0&0&0&0&0&0\\1&0&1&1&0&1&1&1&1&1&0&0&0&0&0&0&0&0&0\\1&1&1&0&0&1&0&1&1&1&0&1&0&0&0&0&0&0&0\\1&0&0&0&0&0&0&0&1&1&1&1&1&1&0&0&0&0&0\\1&1&1&0&0&0&1&0&0&1&1&0&1&1&0&0&0&0&0\\0&0&1&1&0&0&0&1&1&1&0&1&1&0&0&0&0&0&0\\0&0&1&0&0&0&0&0&0&1&1&1&1&1&0&0&0&1&0\\1&1&0&1&1&1&0&0&0&0&1&0&1&1&0&0&0&0&1\\1&1&1&0&1&1&0&0&0&1&0&0&1&0&0&0&0&0&1\\1&0&1&1&0&1&0&1&1&1&0&0&0&0&0&0&0&0&0\\0&1&0&1&0&0&1&1&0&1&1&0&1&0&0&0&0&0&0\\1&0&1&0&0&0&0&1&1&0&1&0&0&0&0&0&0&0&0\\1&0&0&0&0&0&0&0&0&1&1&0&0&0&0&0&0&0&1\\0&0&0&0&0&0&0&0&0&0&0&0&0&1&1&1&0&0&1\\1&0&0&0&0&0&0&0&0&0&0&0&0&0&1&0&1&0&0\\0&0&0&0&0&0&0&0&0&0&0&1&1&1&0&0&0&1&1\\1&0&0&0&0&0&0&0&0&0&1&0&0&0&0&0&1&1&0\\\end{bmatrix}\begin{bmatrix}0&1&0&0&0&0&0&0&0&1&0&0&0&0&0&0&0\\1&1&0&1&0&1&1&1&0&1&1&0&0&0&0&0&0\\0&0&1&1&0&1&1&0&0&0&0&0&0&0&0&0&0\\1&1&0&0&0&0&1&1&1&1&1&0&0&1&0&0&0\\1&1&0&1&0&1&0&1&0&1&0&1&1&0&0&0&0\\1&1&1&0&0&1&0&1&1&1&0&1&0&0&0&0&0\\0&0&0&0&0&0&1&1&1&0&1&1&1&0&0&0&0\\0&1&1&0&1&0&1&0&1&0&0&0&1&1&0&0&1\\1&0&1&1&1&1&0&1&0&1&1&1&1&0&0&0&0\\1&1&0&1&1&1&0&1&0&0&0&1&0&0&0&0&0\\0&1&0&1&1&1&1&1&1&0&1&0&0&0&0&0&0\\1&0&1&0&0&1&1&1&1&1&0&1&0&0&0&0&0\\0&1&0&0&1&0&1&0&0&1&1&0&1&0&0&0&0\\0&0&0&0&0&0&0&0&1&0&1&1&1&0&1&0&0\\1&0&0&0&0&0&0&1&0&0&0&0&1&1&1&0&0\\0&0&0&0&0&0&0&0&0&0&0&1&0&1&1&1&1\\1&0&0&0&0&0&0&0&0&0&1&0&1&0&0&0&1\\\end{bmatrix}\begin{bmatrix}1&0&1&1&1&1&1&1&0&1&0&0&0&0&0\\0&0&1&0&1&1&1&1&0&0&0&1&0&1&0\\0&0&0&0&1&0&1&1&0&1&0&0&1&0&0\\1&0&1&0&1&1&1&0&1&0&1&1&0&0&0\\1&1&0&0&1&0&1&1&1&0&1&0&0&0&0\\0&0&0&0&1&1&1&1&0&1&1&1&0&1&0\\0&1&1&1&0&1&0&1&1&1&0&1&1&0&0\\0&1&1&1&1&1&1&1&1&1&1&0&0&0&0\\1&0&1&1&1&1&1&1&0&0&1&0&0&0&0\\0&0&1&1&1&1&1&1&1&1&0&1&0&0&0\\0&1&0&0&1&1&1&1&1&0&1&0&0&0&0\\0&0&0&1&1&1&1&0&1&1&0&0&1&0&0\\0&1&0&0&1&0&0&1&0&1&1&1&1&1&1\\0&0&0&0&0&0&1&0&1&1&1&1&1&1&0\\0&0&0&0&0&0&0&1&0&0&1&1&1&1&0\\\end{bmatrix}
GenLayerRemoveTooMuchOcean – с невысоким шансом генерирует поверхность на месте океана при условии, что поблизости нет другой поверхности.
7_GenLayerAddIsland.png

8_GenLayerRemoveTooMuchOcean.png
\begin{bmatrix}1&0&1&1&1&1&1&1&0&1&0&0&0&0&0\\0&0&1&0&1&1&1&1&0&0&0&1&0&1&0\\0&0&0&0&1&0&1&1&0&1&0&0&1&0&0\\1&0&1&0&1&1&1&0&1&0&1&1&0&0&0\\1&1&0&0&1&0&1&1&1&0&1&0&0&0&0\\0&0&0&0&1&1&1&1&0&1&1&1&0&1&0\\0&1&1&1&0&1&0&1&1&1&0&1&1&0&0\\0&1&1&1&1&1&1&1&1&1&1&0&0&0&0\\1&0&1&1&1&1&1&1&0&0&1&0&0&0&0\\0&0&1&1&1&1&1&1&1&1&0&1&0&0&0\\0&1&0&0&1&1&1&1&1&0&1&0&0&0&0\\0&0&0&1&1&1&1&0&1&1&0&0&1&0&0\\0&1&0&0&1&0&0&1&0&1&1&1&1&1&1\\0&0&0&0&0&0&1&0&1&1&1&1&1&1&0\\0&0&0&0&0&0&0&1&0&0&1&1&1&1&0\\\end{bmatrix}\begin{bmatrix}0&1&0&1&1&1&1&0&0&0&1&0&1\\1&0&0&1&0&1&1&0&1&0&0&1&0\\0&1&0&1&1&1&0&1&0&1&1&0&1\\1&0&0&1&0&1&1&1&0&1&0&1&0\\0&0&0&1&1&1&1&0&1&1&1&0&1\\1&1&1&0&1&0&1&1&1&0&1&1&0\\1&1&1&1&1&1&1&1&1&1&0&0&1\\0&1&1&1&1&1&1&0&0&1&0&0&0\\0&1&1&1&1&1&1&1&1&0&1&0&1\\1&0&0&1&1&1&1&1&0&1&0&0&1\\0&0&1&1&1&1&0&1&1&0&0&1&0\\1&0&0&1&0&0&1&0&1&1&1&1&1\\0&0&0&0&0&1&0&1&1&1&1&1&1\\\end{bmatrix}
GenLayerAddSnow – с малым шансом генерирует рядом с океаном холодные и снежные биомы.
8_GenLayerRemoveTooMuchOcean.png

9_GenLayerAddSnow.png
\begin{bmatrix}0&1&0&1&1&1&1&0&0&0&1&0&1\\1&0&0&1&0&1&1&0&1&0&0&1&0\\0&1&0&1&1&1&0&1&0&1&1&0&1\\1&0&0&1&0&1&1&1&0&1&0&1&0\\0&0&0&1&1&1&1&0&1&1&1&0&1\\1&1&1&0&1&0&1&1&1&0&1&1&0\\1&1&1&1&1&1&1&1&1&1&0&0&1\\0&1&1&1&1&1&1&0&0&1&0&0&0\\0&1&1&1&1&1&1&1&1&0&1&0&1\\1&0&0&1&1&1&1&1&0&1&0&0&1\\0&0&1&1&1&1&0&1&1&0&0&1&0\\1&0&0&1&0&0&1&0&1&1&1&1&1\\0&0&0&0&0&1&0&1&1&1&1&1&1\\\end{bmatrix}\begin{bmatrix}0&0&3&0&1&1&0&1&0&0&3\\1&0&4&1&1&0&1&0&1&3&0\\0&0&1&0&1&1&1&0&1&0&1\\0&0&1&3&1&1&0&1&1&1&0\\1&1&0&1&0&4&3&1&0&4&1\\3&4&1&1&1&1&1&4&3&0&0\\4&1&1&1&1&4&0&0&3&0&0\\1&3&1&1&1&1&1&1&0&1&0\\0&0&1&4&1&1&4&0&3&0&0\\0&1&1&1&1&0&4&1&0&0&1\\0&0&1&0&0&1&0&1&3&4&1\\\end{bmatrix}
GenLayerEdge – генерирует на поверхности умеренные, холодные и снежные биомы в зависимости от мода слоя GenLayerEdge.Mode:

  • COOL_WARM – генерирует умеренные биомы рядом с холодными или снежными биомами;
  • HEAT_ICE – генерирует холодные биомы рядом с умеренными биомами или поверхностью;
  • SPECIAL – с маленьким шансом добавляет гарантированную генерацию определенного биома вместо условных биомов.
  • Теплый биом: MESACLEARROCK (Столовые горы Плато) или MESA_ROCK (Столовые горы Плато Л);
  • Умеренный биом: JUNGLE (Джунгли);
  • Холодный биом: REDWOOD_TAIGA (Мегатайга);
  • Снежный биом: нет гарантированной генерации.
Пример поочередного использования всех модов.
10_GenLayerAddIsland.png

11_GenLayerEdge.COOL_WARM.png

12_GenLayerEdge.HEAT_ICE.png

13_GenLayerEdge.SPECIAL.png
\begin{bmatrix}0&4&1&1&0&1&0&0&0\\0&0&1&1&1&1&0&1&1\\0&0&3&1&1&0&1&1&0\\1&0&1&1&4&3&1&0&4\\4&1&1&1&1&1&4&3&1\\1&1&1&1&4&1&1&3&0\\3&1&1&1&1&1&1&0&1\\0&1&4&1&1&4&4&3&0\\1&0&1&1&1&4&1&4&0\\\end{bmatrix}\begin{bmatrix}0&2&1&1&1&0&1\\0&3&2&2&0&1&1\\0&2&2&4&3&2&0\\2&1&1&2&2&4&3\\1&1&2&4&2&2&3\\2&2&1&2&2&2&0\\2&4&2&2&4&4&3\\\end{bmatrix}\begin{bmatrix}3&2&2&0&1\\2&2&3&3&2\\1&1&2&2&3\\1&2&3&2&2\\2&1&2&2&2\\\end{bmatrix}\begin{bmatrix}3&2&2&0&1\\2&2&3&3&2\\1&1281&2&2&3\\1&2&3&2&2050\\514&1&2&2&2\\\end{bmatrix}
GenLayerAddMushroomIsland – с маленьким шансом добавляет MUSHROOM_ISLAND (Грибной остров) при условии, что рядом нет поверхности. В данном слое цифры все еще обозначают условные биомы и океан, но при этом в массиве уже может содержаться идентификатор грибного острова.
16_GenLayerAddIsland.png

17_GenLayerAddMushroomIsland.png
\begin{bmatrix}0&0&0&0&0&3&3&3&3\\3&0&0&3&0&3&0&3&3\\0&3&0&0&0&0&0&0&0\\0&0&0&0&0&0&0&0&0\\0&3&0&3&0&0&3&0&3\\2&3&3&0&3&0&0&0&0\\3&0&0&3&0&3&0&0&0\\0&3&3&0&0&3&3&0&0\\1&0&0&0&3&3&0&0&0\\\end{bmatrix}\begin{bmatrix}0&0&3&0&3&0&3\\3&0&0&0&0&0&0\\0&0&0&0&0&0&0\\3&0&3&14&0&3&0\\3&3&0&3&0&0&0\\0&0&3&0&3&0&0\\3&3&0&0&3&3&0\\\end{bmatrix}
GenLayerDeepOcean – преобразует океан в глубокий океан. Также, как и в предыдущем слое, возвращает массив, содержащий одновременно и условные биомы, и идентификаторы биомов.
17_GenLayerAddMushroomIsland.png

18_GenLayerDeepOcean.png
\begin{bmatrix}0&0&3&0&3&0&3\\3&0&0&0&0&0&0\\0&0&0&0&0&0&0\\3&0&3&14&0&3&0\\3&3&0&3&0&0&0\\0&0&3&0&3&0&0\\3&3&0&0&3&3&0\\\end{bmatrix}\begin{bmatrix}0&0&24&0&24\\24&0&0&24&0\\0&3&14&0&3\\3&0&3&0&0\\0&3&0&3&0\\\end{bmatrix}
GenLayerBiome – заменяет все условные биомы на идентификаторы биомов. Биомы выбираются с учетом своего «веса». Чем он больше, тем выше шанс генерации именно этого биома. Если в массиве присутствуют гарантированные биомы, то они в любом случае сгенерируются какой бы «вес» не имели остальные биомы.

Пример с гарантированной генерацией теплых биомов.
18_GenLayerDeepOcean.png

19_GenLayerBiome.png
\begin{bmatrix}1281&1281&2&2&3\\1281&1281&1281&2&2\\1281&1281&1281&2&2\\1&1281&2&2&2\\1&2&2&2&2\\\end{bmatrix}\begin{bmatrix}38&39&27&29&5\\39&38&38&27&27\\38&38&38&4&6\\2&38&1&4&3\\2&27&27&4&29\\\end{bmatrix}

GenLayerBiomeEdge – изменяет биомы в зависимости от температуры соседних биомов, а также создает границу вокруг некоторых биомов.
  • EXTREME_HILLS (Горы) изменяется на EXTREME_HILLS_EDGE (Окраина гор), если рядом есть биомы, не подходящие по температуре;
  • MESA_ROCK (Столовые горы Плато Л) и MESA_CLEAR_ROCK (Столовые горы Плато) изменяются на границе на MESA (Столовые горы);
  • REDWOOD_TAIGA (Мегатайга) изменяется на границе на TAIGA (Тайга);
  • DESERT (Пустыня) изменяется на EXTREME_HILLS_WITH_TREES (Горы+), если рядом есть ICE_PLAINS (Тундра);
  • SWAMPLAND(Болото) изменяется на:
    • PLAINS (Равнина), если рядом есть DESERT (Пустыня), COLD_TAIGA (Холодная тайга) или ICE_PLAINS (Тундра);
    • JUNGLE_EDGE (Окраина джунглей), если рядом нет DESERT (Пустыня), COLD_TAIGA (Холодная тайга) и ICE_PLAINS (Тундра), но есть JUNGLE (Джунгли).
Пример появления границы.
21_GenLayerZoom.png

22_GenLayerBiomeEdge.png
\begin{bmatrix}39&39&38&38&38&38&38&38&38&38&38\\38&38&38&38&38&38&38&38&38&38&38\\38&38&38&38&38&38&38&38&38&38&38\\38&38&38&38&38&38&38&38&38&38&38\\38&38&38&38&38&38&38&38&38&38&4\\38&38&38&38&38&38&38&38&38&4&4\\2&2&38&38&38&1&1&38&4&4&4\\2&2&2&38&1&1&1&1&1&4&4\\2&2&2&27&27&1&27&1&4&4&4\\2&2&2&27&27&27&27&27&27&4&4\\2&2&27&27&27&27&27&27&27&27&4\\\end{bmatrix}\begin{bmatrix}38&38&38&38&38&38&38&38&38\\38&38&38&38&38&38&38&38&38\\38&38&38&38&38&38&38&38&38\\38&38&38&38&38&38&38&38&37\\37&38&38&38&37&37&38&37&4\\2&37&38&37&1&1&37&4&4\\2&2&37&1&1&1&1&1&4\\2&2&27&27&1&27&1&4&4\\2&2&27&27&27&27&27&27&4\\\end{bmatrix}
GenLayerHills – изменяет биомы, с невысоким шансом заменяя их в основном горными аналогами, а также с низким шансом изменяет биом на редкую вариацию этого биома.
22_GenLayerBiomeEdge.png

44_GenLayerHills.png
\begin{bmatrix}38&38&38&38&38&38&38&38&38\\38&38&38&38&38&38&38&38&38\\38&38&38&38&38&38&38&38&38\\38&38&38&38&38&38&38&38&37\\37&38&38&38&37&37&38&37&4\\2&37&38&37&1&1&37&4&4\\2&2&37&1&1&1&1&1&4\\2&2&27&27&1&27&1&4&4\\2&2&27&27&27&27&27&27&4\\\end{bmatrix}\begin{bmatrix}38&37&38&38&38&38&37\\38&37&38&38&38&37&38\\37&38&38&38&38&37&38\\37&37&38&37&37&38&37\\37&38&37&1&1&37&4\\&2&37&1&4&1&1&1\\&2&27&27&1&27&1&4\\\end{bmatrix}
GenLayerRareBiome – с низким шансом изменяет PLAINS (Равнина) на MUTATED_PLAINS (Подсолнечное поле).
44_GenLayerHills.png

45_GenLayerRareBiome.png
\begin{bmatrix}18&4&18&4&4&1&4\\18&4&4&18&4&4&1\\4&18&4&4&4&4&4\\3&18&4&4&1&1&1\\3&4&18&1&4&1&1\\3&1&4&1&1&5&1\\1&18&1&5&5&5&5\\\end{bmatrix}\begin{bmatrix}4&4&18&4&4\\18&4&4&4&4\\18&4&4&1&1\\4&18&129&4&1\\1&4&1&1&5\\\end{bmatrix}
GenLayerShore – создает береговую линию или границу, но не такую большую, как с помощью GenLayerBiomeEdge:
  • MUSHROOM_ISLAND (Грибной остров) изменяется на MUSHROOM_ISLAND_SHORE (Берег грибного острова), если рядом есть океан;
  • Любой биом класса BiomeJungle.class (включая дочерние) изменяется на:
    • JUNGLE_EDGE(Окраина джунглей), если рядом есть другой биом, кроме:
      • Биомов класса BiomeJungle.class;
      • Биомов FOREST (Лес) и TAIGA (Тайга);
      • Океанов;
    • BEACH (Пляж), если выполнены предыдущие два условия и рядом есть океан;
  • EXTREME_HILLS (Горы), EXTREME_HILLS_WITH_TREES (Горы+) и EXTREME_HILLS_EDGE (Окраина гор) изменяется на STONE_BEACH (Каменный пляж), если рядом есть океан;
  • Снежные биомы (Biome.enableSnow = true) изменяются на COLD_BEACH (Холодный пляж), если рядом есть океан;
  • MESA (Столовые горы) и MESA_ROCK (Столовые горы Плато Л) изменяются на DESERT (Пустыня), если рядом есть отличный от Столовых гор биом, не являющийся океаном (это не береговая линия);
  • Оставшиеся биомы кроме SWAMPLAND изменяет на BEACH (Пляж), если рядом есть океан.
Пример с грибным островом.
48_GenLayerZoom.png

49_GenLayerShore.png
\begin{bmatrix}0&0&0&3&14&14&14\\0&0&0&3&14&14&14\\0&0&0&14&14&14&14\\3&0&0&14&14&14&14\\3&0&14&14&14&14&14\\14&14&14&14&14&14&14\\3&14&14&14&14&14&14\\\end{bmatrix}\begin{bmatrix}0&0&25&14&14\\0&0&15&14&14\\0&0&15&14&14\\0&15&14&14&14\\15&14&14&14&14\\\end{bmatrix}
GenLayerSmooth – сглаживает массив биомов.
51_GenLayerZoom.png

52_GenLayerSmooth.png
\begin{bmatrix}38&37&37&37&37&37&37&37\\38&38&37&37&37&37&37&37\\38&37&37&37&2&37&37&37\\37&37&2&2&2&37&37&2\\37&2&2&2&2&2&37&2\\37&2&2&2&2&2&2&2\\37&2&2&2&2&2&2&2\\2&2&2&2&2&2&2&2\\\end{bmatrix}\begin{bmatrix}37&37&37&37&37&37\\37&37&37&37&37&37\\37&2&2&2&37&37\\2&2&2&2&2&2\\2&2&2&2&2&2\\2&2&2&2&2&2\\\end{bmatrix}
GenLayerRiverInit – заполняет массив псевдослучайными числами.
18_GenLayerDeepOcean.png

71_GenLayerRiverInit.png
\begin{bmatrix}1281&1281&2&2&3\\1281&1281&1281&2&2\\1281&1281&1281&2&2\\1&1281&2&2&2\\1&2&2&2&2\\\end{bmatrix}\begin{bmatrix}201635&35883&92557&144189\\265157&74940&13859&156217\\80491&225585&34907&207923\\85634&240867&235846&275968\\\end{bmatrix}
GenLayerRiver – создает на границах различающихся цифр реку.
77_GenLayerZoom.png

78_GenLayerRiver.png
\begin{bmatrix}80491&80491&80491&80491&80491&80491&80491&80491&80491&80491\\85634&80491&80491&80491&80491&80491&80491&80491&80491&80491\\85634&85634&85634&80491&80491&80491&80491&80491&80491&80491\\85634&85634&85634&80491&80491&80491&80491&80491&80491&80491\\85634&85634&85634&85634&80491&80491&80491&80491&80491&80491\\85634&85634&85634&85634&80491&80491&80491&80491&80491&80491\\85634&85634&85634&85634&80491&80491&80491&80491&80491&240867\\85634&85634&85634&85634&85634&240867&80491&80491&80491&240867\\85634&85634&85634&85634&85634&240867&240867&80491&80491&240867\\85634&85634&85634&85634&240867&240867&240867&240867&240867&240867\\\end{bmatrix}\begin{bmatrix}7&7&-1&-1&-1&-1&-1&-1\\7&7&7&-1&-1&-1&-1&-1\\-1&7&7&-1&-1&-1&-1&-1\\-1&-1&7&7&-1&-1&-1&-1\\-1&-1&7&7&-1&-1&-1&-1\\-1&-1&7&7&-1&-1&-1&-1\\-1&-1&-1&7&7&-1&-1&-1\\-1&-1&-1&7&7&-1&-1&-1\\\end{bmatrix}
GenLayerRiverMix – накладывает массив с рекой поверх массива с биомами с некоторым ограничениями:
  • Река не накладывается на OCEAN (Океан) и DEEP_OCEAN (Глубокий океан);
  • Если река накладывается на ICEPLAINS (Тундра), то биом заменяется на FROZERRIVER (Замерзшая река);
  • Если река накладывается на MUSHROOM_ISLAND (Грибной остров), то биом заменяется на MUSHROOM_ISLAND_SHORE (Берег грибного острова).
52_GenLayerSmooth.png

79_GenLayerSmooth.png

80_GenLayerRiverMix.png
\begin{bmatrix}37&37&37&37&37&37\\37&37&37&37&37&37\\37&2&2&2&37&37\\2&2&2&2&2&2\\2&2&2&2&2&2\\2&2&2&2&2&2\\\end{bmatrix}\begin{bmatrix}7&7&-1&-1&-1&-1\\7&7&-1&-1&-1&-1\\-1&7&7&-1&-1&-1\\-1&7&7&-1&-1&-1\\-1&7&7&-1&-1&-1\\-1&-1&7&7&-1&-1\\\end{bmatrix}\begin{bmatrix}7&7&37&37&37&37\\7&7&37&37&37&37\\37&7&7&2&37&37\\2&7&7&2&2&2\\2&7&7&2&2&2\\2&2&7&7&2&2\\\end{bmatrix}
GenLayerVoronoiZoom – растягивает весь массив, делая его больше (не изменяя масштаба) и заполняя пустые ячейки.
\begin{bmatrix}7&7&37&37&37&37\\7&7&37&37&37&37\\37&7&7&2&37&37\\2&7&7&2&2&2\\2&7&7&2&2&2\\2&2&7&7&2&2\\\end{bmatrix}\begin{bmatrix}7&7&7&7&7&37&37&37&37&37&37&37&37&37&37&37\\7&7&7&7&7&37&37&37&37&37&37&37&37&37&37&37\\7&7&7&7&37&37&37&37&37&37&37&37&37&37&37&37\\37&7&7&7&37&37&37&37&2&2&2&37&37&37&37&37\\37&7&7&7&7&37&37&2&2&2&2&2&2&37&37&37\\37&7&7&7&7&7&7&2&2&2&2&2&2&37&37&37\\37&37&7&7&7&7&7&7&2&2&2&2&37&37&37&37\\7&7&7&7&7&7&7&7&2&2&2&2&37&37&37&37\\7&7&7&7&7&7&7&7&2&2&2&2&2&2&37&37\\7&7&7&7&7&7&7&7&2&2&2&2&2&2&2&2\\7&7&7&7&7&7&7&7&7&2&2&2&2&2&2&2\\7&7&7&7&7&7&7&7&7&7&2&2&2&2&2&2\\7&7&7&7&7&7&7&7&2&2&2&2&2&2&2&2\\7&7&7&7&7&7&7&7&2&2&2&2&2&2&2&2\\7&7&7&7&7&7&7&7&7&2&2&2&2&2&2&2\\7&7&7&2&2&7&7&7&7&7&2&2&2&2&2&2\\\end{bmatrix}

1.2 Алгоритм генерации
Алгоритм, по которому происходит генерация биомов в Обычном мире, можно посмотреть в методе GenLayer.initializeAllBiomeGenerators(…):
Java:
public static GenLayer[] initializeAllBiomeGenerators(long seed, WorldType worldType, ChunkGeneratorSettings settings)
{
    GenLayer genlayer = new GenLayerIsland(1L);
    genlayer = new GenLayerFuzzyZoom(2000L, genlayer);
    GenLayer genlayeraddisland = new GenLayerAddIsland(1L, genlayer);
    GenLayer genlayerzoom = new GenLayerZoom(2001L, genlayeraddisland);
    GenLayer genlayeraddisland1 = new GenLayerAddIsland(2L, genlayerzoom);
    genlayeraddisland1 = new GenLayerAddIsland(50L, genlayeraddisland1);
    genlayeraddisland1 = new GenLayerAddIsland(70L, genlayeraddisland1);
    GenLayer genlayerremovetoomuchocean = new GenLayerRemoveTooMuchOcean(2L, genlayeraddisland1);
    GenLayer genlayeraddsnow = new GenLayerAddSnow(2L, genlayerremovetoomuchocean);
    GenLayer genlayeraddisland2 = new GenLayerAddIsland(3L, genlayeraddsnow);
    GenLayer genlayeredge = new GenLayerEdge(2L, genlayeraddisland2, GenLayerEdge.Mode.COOL_WARM);
    genlayeredge = new GenLayerEdge(2L, genlayeredge, GenLayerEdge.Mode.HEAT_ICE);
    genlayeredge = new GenLayerEdge(3L, genlayeredge, GenLayerEdge.Mode.SPECIAL);
    GenLayer genlayerzoom1 = new GenLayerZoom(2002L, genlayeredge);
    genlayerzoom1 = new GenLayerZoom(2003L, genlayerzoom1);
    GenLayer genlayeraddisland3 = new GenLayerAddIsland(4L, genlayerzoom1);
    GenLayer genlayeraddmushroomisland = new GenLayerAddMushroomIsland(5L, genlayeraddisland3);
    GenLayer genlayerdeepocean = new GenLayerDeepOcean(4L, genlayeraddmushroomisland);
    GenLayer genlayer4 = GenLayerZoom.magnify(1000L, genlayerdeepocean, 0);
    int i = 4;
    int j = i;

    if (settings != null)
    {
        i = settings.biomeSize;
        j = settings.riverSize;
    }

    if (worldType == WorldType.LARGE_BIOMES)
    {
        i = 6;
    }

    i = getModdedBiomeSize(worldType, i);

    GenLayer lvt_7_1_ = GenLayerZoom.magnify(1000L, genlayer4, 0);
    GenLayer genlayerriverinit = new GenLayerRiverInit(100L, lvt_7_1_);
    GenLayer genlayerbiomeedge = worldType.getBiomeLayer(seed, genlayer4, settings);
    GenLayer lvt_9_1_ = GenLayerZoom.magnify(1000L, genlayerriverinit, 2);
    GenLayer genlayerhills = new GenLayerHills(1000L, genlayerbiomeedge, lvt_9_1_);
    GenLayer genlayer5 = GenLayerZoom.magnify(1000L, genlayerriverinit, 2);
    genlayer5 = GenLayerZoom.magnify(1000L, genlayer5, j);
    GenLayer genlayerriver = new GenLayerRiver(1L, genlayer5);
    GenLayer genlayersmooth = new GenLayerSmooth(1000L, genlayerriver);
    genlayerhills = new GenLayerRareBiome(1001L, genlayerhills);

    for (int k = 0; k < i; ++k)
    {
        genlayerhills = new GenLayerZoom((long)(1000 + k), genlayerhills);

        if (k == 0)
        {
            genlayerhills = new GenLayerAddIsland(3L, genlayerhills);
        }

        if (k == 1 || i == 1)
        {
            genlayerhills = new GenLayerShore(1000L, genlayerhills);
        }
    }

    GenLayer genlayersmooth1 = new GenLayerSmooth(1000L, genlayerhills);
    GenLayer genlayerrivermix = new GenLayerRiverMix(100L, genlayersmooth1, genlayersmooth);
    GenLayer genlayer3 = new GenLayerVoronoiZoom(10L, genlayerrivermix);
    genlayerrivermix.initWorldGenSeed(seed);
    genlayer3.initWorldGenSeed(seed);
    return new GenLayer[] {genlayerrivermix, genlayer3, genlayerrivermix};
}
Но более наглядно процесс генерации можно представить в виде структуры, опустив некоторые слои (GenLayerZoom, GenLayerAddIsland, GenLayerSmooth и пр.):

123.jpg

GenLayerVoronoiZoom является последним слоем в алгоритме и возвращает именно тот самый одномерный массив, в котором записаны идентификаторы всех биомов в чанке. Данный слой, как и почти все остальные слои, генерирует свой массив данных, используя массив данных своего родителя. Иначе говоря, чтобы возвратить нам массив длиной 16 * 16, состоящий из идентификаторов биомов в данном чанке, нам необходимо сначала определить массив данных слоя GenLayerRiverMix (массив биомов/рек размером 6 * 6), т.к. по стандартному алгоритму этот слой является родителем слоя GenLayerVoronoiZoom. А чтобы GenLayerRiverMix смог определить свой массив данных, ему необходимы массивы данных GenLayerHills (массив биомов размером 6 * 6) и GenLayerRiver (массив рек размером 6 * 6). И так каждый слой зависит от слоя своего родителя вплоть до GenLayerIsland, который ни от кого не зависит.

Метод GenLayer.getInts(...) принимает на вход четыре параметра:
  • areaX и areaY - это смещения по x и z. GenLayerVoronoiZoom принимает значения координат из мира, но эти смещения всегда будут изменяться. Если мы получим массив данных из GenLayerVoronoiZoom, а потом сдвинемся на 1 блок и снова получим массив данных, то нетрудно понять, что во втором массиве все биомы сдвинутся тоже на 1 блок. Но чтобы добиться изменения смещения, к примеру, в самом первом слое GenLayerIsland на 1, нужно пройти куда больше. Это объясняется тем, что изначально чанки представляются в меньших масштабах для более быстрой генерации, после чего много раз масштабируются слоями до необходимых размеров;
  • areaWidth - длина, которая отсчитывается по оси, аналогичной оси z в мире;
  • areaHeight - длина, которая отсчитывается по оси, аналогичной оси x в мире.
Возвращает данный метод массив данных размером areaWidth * areaHeight.
Информация записывается в массив по формуле aint[j + i * areaWidth], где i и j представляют из себя координаты x и z в данном массиве. В качестве примера разберем метод слоя GenLayerRemoveTooMuchOcean:
Java:
public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight) {
    int i = areaX - 1;
    int j = areaY - 1;
    int k = areaWidth + 2;
    int l = areaHeight + 2;
    int[] aint = this.parent.getInts(i, j, k, l);
    int[] aint1 = IntCache.getIntCache(areaWidth * areaHeight);

    for (int i1 = 0; i1 < areaHeight; ++i1) {
        for (int j1 = 0; j1 < areaWidth; ++j1) {
            int k1 = aint[j1 + 1 + (i1 + 1 - 1) * (areaWidth + 2)];
            int l1 = aint[j1 + 1 + 1 + (i1 + 1) * (areaWidth + 2)];
            int i2 = aint[j1 + 1 - 1 + (i1 + 1) * (areaWidth + 2)];
            int j2 = aint[j1 + 1 + (i1 + 1 + 1) * (areaWidth + 2)];
            int k2 = aint[j1 + 1 + (i1 + 1) * k];
            aint1[j1 + i1 * areaWidth] = k2;
            this.initChunkSeed((long) (j1 + areaX), (long) (i1 + areaY));

            if (k2 == 0 && k1 == 0 && l1 == 0 && i2 == 0 && j2 == 0 && this.nextInt(2) == 0) {
                aint1[j1 + i1 * areaWidth] = 1;
            }
        }
    }

    return aint1;
}
Чтобы заполнить собственный массив данных aint1 необходимо определить массив данных нашего родителя aint. Размер массива родительского слоя увеличивается на 1 во все стороны.
Java:
int i = areaX - 1;
int j = areaY - 1;
int k = areaWidth + 2;
int l = areaHeight + 2;
int[] aint = this.parent.getInts(i, j, k, l);
Определяем размеры нашего массива.
Java:
int[] aint1 = IntCache.getIntCache(areaWidth * areaHeight);
В данном цикле заполним массив данными.
Java:
for (int i1 = 0; i1 < areaHeight; ++i1) {
    for (int j1 = 0; j1 < areaWidth; ++j1) {

    }
}
С первого взгляда не ясно какие значения мы берем из массива родителя:
Java:
int k1 = aint[j1 + 1 + (i1 + 1 - 1) * (areaWidth + 2)];
int l1 = aint[j1 + 1 + 1 + (i1 + 1) * (areaWidth + 2)];
int i2 = aint[j1 + 1 - 1 + (i1 + 1) * (areaWidth + 2)];
int j2 = aint[j1 + 1 + (i1 + 1 + 1) * (areaWidth + 2)];
int k2 = aint[j1 + 1 + (i1 + 1) * k];
Но если немного подредактируем код, то все сразу станет на свои места.
Возьмем точку k2. Родительский массив во все стороны был увеличен на 1 по сравнению с нашим массивом, поэтому можно сразу догадаться, что если (i1; j1) - координаты точки в нашем массиве aint1, то (i1 + 1; j1 + 1) будут координатами той же самой точки, но в массиве aint, а k - длина по оси z массива aint. Остальные же точки являются "соседями" нашей точки в родительском массиве (их координаты отличаются на +/-1).
Java:
int k1 = aint[j1 + 1 + (i1 + 0) * k];
int l1 = aint[j1 + 2 + (i1 + 1) * k];
int i2 = aint[j1 + 0 + (i1 + 1) * k];
int j2 = aint[j1 + 1 + (i1 + 2) * k];
int k2 = aint[j1 + 1 + (i1 + 1) * k]; // Это наша точка
Заранее переносим значение из родительского массива в наш.
Java:
aint1[j1 + i1 * areaWidth] = k2;
Инициализируем чанковый сид, основанный на сиде мира и смещениях. Сам чанковый сид используется при получении псевдослучайных чисел.
Java:
this.initChunkSeed((long) (j1 + areaX), (long) (i1 + areaY));
Если все точки являются океаном и псевдослучайное число будет равно 0, тогда на месте точки (i1, j1) появится поверхность.
Java:
if (k2 == 0 && k1 == 0 && l1 == 0 && i2 == 0 && j2 == 0 && this.nextInt(2) == 0) {
    aint1[j1 + i1 * areaWidth] = 1;
}

1.3 BiomeManager
При генерации биома важную роль играет то, к каким типам он относится. Если биом не имеет ни одного типа, то он не сможет сгенерироваться в Обычном мире с помощью GenLayerBiome. В BiomeManager.BiomeType определены 4 типа биомов:
  • DESERT- теплый (Пустыня, Саванна, Равнина);
  • WARM - умеренный (Лес, Темный лес, Горы, Равнина, Березовый лес, Болото);
  • COOL - холодный (Лес, Горы, Тайга, Равнина);
  • ICY - снежный (Тундра, Холодная тайга).
1.4 BiomeDictionary
BiomeDictionary упрощает работу с биомами и позволяет взаимодействовать с биомами из других модов.

По умолчанию всем биомам, зарегистрированным в BiomeDictionary, присваиваются типы на основе их свойств (температура, растительность, влажность и т.д.). Если вы регистрируете собственный биом, не указав ни одного типа, то биому будут самостоятельно присвоены типы на основе его свойств. Алгоритм можно посмотреть в методе BiomeDictionary.makeBestGuess(…). Перечень всех стандартных типов можно посмотреть в BiomeDictionary.Type.

Также можно добавить собственный тип, определив его с помощью метода BiomeDictionary.Type.getType(…). Использование одного и того же типа в разных модах позволит взаимодействовать с чужими биомами и использовать, например, собственные генераторы на территории всех биомов с данным типом.

2 Собственный биом

2.1 Регистрация биома
Добавим небольшой интерфейс IBiome, который потребуется для регистрации биомов.
Java:
package ddooss.util.interfaces;

public interface IBiome {
    /**
     * Регистрация биома происходит в этом методе
     */
    public void registerBiome();
}
Теперь добавим класс BiomeInit. Здесь будем объявлять свои биомы Biome и типы BiomeDictionary.Type, а в методе BiomeInit.initBiomes() вызывать регистрацию.
Java:
package ddooss.init;

import java.util.ArrayList;
import java.util.List;

import ddooss.util.enums.EBiome;
import ddooss.util.interfaces.IBiome;
import ddooss.world.biome.BiomeLapis;
import net.minecraft.world.biome.Biome;
import net.minecraftforge.common.BiomeDictionary;

public class BiomeInit {
     /**
     * Список наших биомов
     */
    public static final List<Biome> BIOMES = new ArrayList<Biome>();
    /**
     * Метод, в котором вызываем регистрацию всех биомов из BIOMES
     */
    public static void initBiomes() {
        for (Biome biome : BIOMES) {
            if (biome instanceof IBiome) {
                ((IBiome) biome).registerBiome();
            }
        }
    }
}
Сам метод BiomeInit.initBiomes() будем вызывать на стадии преинициализации мода.
Java:
public void preInit(FMLPreInitializationEvent event) {
    BiomeInit.initBiomes();
}
Теперь добавим перечисления EBiome, где укажем необходимые для генерации свойства биома.
Java:
package ddooss.util.enums;

import ddooss.init.BiomeInit;
import net.minecraftforge.common.BiomeDictionary;
import net.minecraftforge.common.BiomeManager;

public enum EBiome {
    /**
     * Окраина лазуритовой земли, Лазуритовая долина
     */
    LAPIS(BiomeInit.LAPIS),
    /**
     * Лазуритовая земля
     */
    LAPISLAND(BiomeManager.BiomeType.WARM, 10, BiomeInit.LAPIS);

    private final BiomeManager.BiomeType biomeType;

    private final int weight;

    private final BiomeDictionary.Type[] types;

    EBiome(BiomeDictionary.Type... types) {
        this(null, 0, types);
    }

    EBiome(BiomeManager.BiomeType biomeType, int weight, BiomeDictionary.Type... types) {
        this.biomeType = biomeType;
        this.weight = weight;
        this.types = types;
    }

    public BiomeManager.BiomeType getBiomeType() {
        return this.biomeType;
    }

    public int getWeight() {
        return this.weight;
    }

    public BiomeDictionary.Type[] getTypes() {
        return this.types;
    }
}
Добавим абстрактный класс BiomeBase. Если мы указываем вес биома, равный 0, то он не будет генерироваться с помощью слоя GenLayerBiome. Тем не менее, можно добавить свои способы генерирования такого биома по аналогии слоя GenLayerRareBiome.
Java:
package ddooss.world.biome;

import ddooss.init.BiomeInit;
import ddooss.lib.Reference;
import ddooss.util.enums.EBiome;
import ddooss.util.interfaces.IBiome;
import net.minecraft.world.biome.Biome;
import net.minecraftforge.common.BiomeDictionary;
import net.minecraftforge.common.BiomeManager;
import net.minecraftforge.common.BiomeManager.BiomeEntry;
import net.minecraftforge.fml.common.registry.ForgeRegistries;

public abstract class BiomeBase extends Biome implements IBiome {

    // Тип BiomeType, определяющий генерацию биома
    private final BiomeManager.BiomeType biomeType;

    // Вес биома
    private final int weight;

    // Типы биома
    private final BiomeDictionary.Type[] types;

    public BiomeBase(String registryName, Biome.BiomeProperties properties, EBiome eBiome) {
        super(properties);
        this.setRegistryName(Reference.MODID, registryName);
        this.biomeType = eBiome.getBiomeType();
        this.weight = eBiome.getWeight();
        this.types = eBiome.getTypes();
        BiomeInit.BIOMES.add(this);
    }

    @Override
    public void registerBiome() {
        ForgeRegistries.BIOMES.register(this);
        BiomeDictionary.addTypes(this, this.types);

        if (this.weight > 0) {
            BiomeManager.addBiome(biomeType, new BiomeEntry(this, this.weight));
            BiomeManager.addSpawnBiome(this);
        }
    }
}
Добавим класс биома BiomeLapis. У нас будет 3 варианта данного биома, которые определены в перечислении BiomeLapis.LapisType:
  • NORMAL – равнина с изредка встречающимися деревьями;
  • EDGE – граница, представляющая из себя небольшие горы;
  • MUTATED – равнина с большим количеством деревьев.
Java:
package ddooss.world.biome;

import java.util.Random;

import ddooss.util.enums.EBiome;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.feature.WorldGenAbstractTree;

public class BiomeLapis extends BiomeBase {

    private final LapisType type;

    public BiomeLapis(String registryName, Biome.BiomeProperties properties, EBiome eBiome, LapisType type) {
        super(registryName, properties, eBiome);
        this.type = type;

        if (this.type == LapisType.EDGE) {
            this.decorator.extraTreeChance = 0F;
            this.topBlock = Blocks.STONE.getDefaultState();
            this.fillerBlock = Blocks.STONE.getDefaultState();
        } else if (this.type == LapisType.MUTATED) {
            this.decorator.treesPerChunk = 3;
        }
    }

    @Override
    public WorldGenAbstractTree getRandomTreeFeature(Random rand) {
        return this.type == LapisType.MUTATED ? BIG_TREE_FEATURE : TREE_FEATURE;
    }

    @Override
    public int getGrassColorAtPos(BlockPos pos) {
        return this.type == LapisType.EDGE ? super.getGrassColorAtPos(pos) : 0x00ffff;
    }

    @Override
    public int getFoliageColorAtPos(BlockPos pos) {
        return this.type == LapisType.EDGE ? super.getFoliageColorAtPos(pos) : 0x00ffff;
    }

    public static enum LapisType {
        NORMAL, EDGE, MUTATED;
    }
}
Определим новые биомы в классе BiomeInit.
Java:
public static final Biome LAPISLAND = new BiomeLapis("lapisalnd", new Biome.BiomeProperties("Lapisland").setBaseHeight(-0.1F).setHeightVariation(0.1F).setTemperature(0.8F).setRainfall(0.7F), EBiome.LAPISLAND, BiomeLapis.LapisType.NORMAL);

public static final Biome LAPISLAND_EDGE = new BiomeLapis("lapisalnd_edge", new Biome.BiomeProperties("Lapisland Edge").setBaseHeight(0.9F).setHeightVariation(0.1F).setTemperature(0.8F).setRainfall(0.7F), EBiome.LAPIS, BiomeLapis.LapisType.EDGE);

public static final Biome LAPISVALLEY = new BiomeLapis("lapisvalley", new Biome.BiomeProperties("Lapisvalley").setBaseBiome("lapisalnd").setBaseHeight(-0.1F).setHeightVariation(0.1F).setTemperature(0.8F).setRainfall(0.7F), EBiome.LAPIS, BiomeLapis.LapisType.MUTATED);
Теперь в нашем мире генерируется LAPISLAND (Лазуритовая земля) и редкая вариация LAPISVALLEY (Лазуритовая долина). Осталось добавить границу.

2.2 Использование собственных GenLayer
На данный момент в Forge нет инструментов, которые могли бы изменять какой-то конкретный слой GenLayer, поэтому придется использовать собственный алгоритм генерации биомов.

Добавим класс TerrainHandler и событие InitBiomeGens, в котором укажем свой алгоритм генерации биомов. Данное событие не поддерживает возможность использовать настройки из расширенного типа мира.
Java:
package ddooss.handler;

import ddooss.world.gen.layer.GenLayerCustom;
import net.minecraft.world.gen.layer.GenLayer;
import net.minecraftforge.event.terraingen.WorldTypeEvent.InitBiomeGens;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

public class TerrainHandler {
    @SubscribeEvent
    public void initializeAllBiomeGenerators(InitBiomeGens event) {
        GenLayer[] genlayer = GenLayerCustom.initializeAllBiomeGenerators(event.getSeed(), event.getWorldType());
        event.setNewBiomeGens(genlayer);
    }
}
Регистрировать событие будем на стадии преинициализации мода. Скажу сразу, что @Mod.EventBusSubscriber нельзя использовать, поскольку используется событие MinecraftForge.TERRAIN_GEN_BUS, а не MinecraftForge.EVENT_BUS.
Java:
public void preInit(FMLPreInitializationEvent event) {
    BiomeInit.initBiomes();
    MinecraftForge.TERRAIN_GEN_BUS.register(new TerrainHandler());
}
Осталось добавить новые слои GenLayer. Новый алгоритм генерации определим в слое GenLayerCustom. Небольшую границу будем генерировать в GenLayerShoreCustom, а также отключим генерацию рек на территории наших биомов в GenLayerRiverMixCustom.

Абстрактный класс GenLayerCustom:
Java:
package ddooss.world.gen.layer;

import net.minecraft.world.WorldType;
import net.minecraft.world.gen.layer.GenLayer;
import net.minecraft.world.gen.layer.GenLayerAddIsland;
import net.minecraft.world.gen.layer.GenLayerAddMushroomIsland;
import net.minecraft.world.gen.layer.GenLayerAddSnow;
import net.minecraft.world.gen.layer.GenLayerBiome;
import net.minecraft.world.gen.layer.GenLayerBiomeEdge;
import net.minecraft.world.gen.layer.GenLayerDeepOcean;
import net.minecraft.world.gen.layer.GenLayerEdge;
import net.minecraft.world.gen.layer.GenLayerFuzzyZoom;
import net.minecraft.world.gen.layer.GenLayerHills;
import net.minecraft.world.gen.layer.GenLayerIsland;
import net.minecraft.world.gen.layer.GenLayerRareBiome;
import net.minecraft.world.gen.layer.GenLayerRemoveTooMuchOcean;
import net.minecraft.world.gen.layer.GenLayerRiver;
import net.minecraft.world.gen.layer.GenLayerRiverInit;
import net.minecraft.world.gen.layer.GenLayerSmooth;
import net.minecraft.world.gen.layer.GenLayerVoronoiZoom;
import net.minecraft.world.gen.layer.GenLayerZoom;

public abstract class GenLayerCustom extends GenLayer {

    public GenLayerCustom(long seed) {
        super(seed);
    }

    public static GenLayer[] initializeAllBiomeGenerators(long seed, WorldType worldType) {
        GenLayer genlayer = new GenLayerIsland(1L);
        genlayer = new GenLayerFuzzyZoom(2000L, genlayer);
        GenLayer genlayeraddisland = new GenLayerAddIsland(1L, genlayer);
        GenLayer genlayerzoom = new GenLayerZoom(2001L, genlayeraddisland);
        GenLayer genlayeraddisland1 = new GenLayerAddIsland(2L, genlayerzoom);
        genlayeraddisland1 = new GenLayerAddIsland(50L, genlayeraddisland1);
        genlayeraddisland1 = new GenLayerAddIsland(70L, genlayeraddisland1);
        GenLayer genlayerremovetoomuchocean = new GenLayerRemoveTooMuchOcean(2L, genlayeraddisland1);
        GenLayer genlayeraddsnow = new GenLayerAddSnow(2L, genlayerremovetoomuchocean);
        GenLayer genlayeraddisland2 = new GenLayerAddIsland(3L, genlayeraddsnow);
        GenLayer genlayeredge = new GenLayerEdge(2L, genlayeraddisland2, GenLayerEdge.Mode.COOL_WARM);
        genlayeredge = new GenLayerEdge(2L, genlayeredge, GenLayerEdge.Mode.HEAT_ICE);
        genlayeredge = new GenLayerEdge(3L, genlayeredge, GenLayerEdge.Mode.SPECIAL);
        GenLayer genlayerzoom1 = new GenLayerZoom(2002L, genlayeredge);
        genlayerzoom1 = new GenLayerZoom(2003L, genlayerzoom1);
        GenLayer genlayeraddisland3 = new GenLayerAddIsland(4L, genlayerzoom1);
        GenLayer genlayeraddmushroomisland = new GenLayerAddMushroomIsland(5L, genlayeraddisland3);
        GenLayer genlayerdeepocean = new GenLayerDeepOcean(4L, genlayeraddmushroomisland);
        GenLayer genlayer4 = GenLayerZoom.magnify(1000L, genlayerdeepocean, 0);
        int biomeSize = 4;
        int riverSize = biomeSize;

        if (worldType == WorldType.LARGE_BIOMES) {
            biomeSize = 6;
        }

        biomeSize = GenLayer.getModdedBiomeSize(worldType, biomeSize);
        GenLayer lvt_7_1_ = GenLayerZoom.magnify(1000L, genlayer4, 0);
        GenLayer genlayerriverinit = new GenLayerRiverInit(100L, lvt_7_1_);
        GenLayer genlayerbiome = new GenLayerBiome(200L, genlayer4, worldType, null);
        GenLayer ret = GenLayerZoom.magnify(1000L, genlayerbiome, 2);
        GenLayer genlayerbiomeedge = new GenLayerBiomeEdge(1000L, ret);
        GenLayer lvt_9_1_ = GenLayerZoom.magnify(1000L, genlayerriverinit, 2);
        GenLayer genlayerhills = new GenLayerHills(1000L, genlayerbiomeedge, lvt_9_1_);
        GenLayer genlayer5 = GenLayerZoom.magnify(1000L, genlayerriverinit, 2);
        genlayer5 = GenLayerZoom.magnify(1000L, genlayer5, riverSize);
        GenLayer genlayerriver = new GenLayerRiver(1L, genlayer5);
        GenLayer genlayersmooth = new GenLayerSmooth(1000L, genlayerriver);
        genlayerhills = new GenLayerRareBiome(1001L, genlayerhills);

        for (int k = 0; k < biomeSize; k++) {
            genlayerhills = new GenLayerZoom((long) (1000 + k), genlayerhills);

            if (k == 0) {
                genlayerhills = new GenLayerAddIsland(3L, genlayerhills);
            }

            if (k == 1 || biomeSize == 1) {
                genlayerhills = new GenLayerShoreCustom(1000L, genlayerhills); // Новый генератор береговых линий и небольших границ
            }
        }

        GenLayer genlayersmooth1 = new GenLayerSmooth(1000L, genlayerhills);
        GenLayer genlayerrivermix = new GenLayerRiverMixCustom(100L, genlayersmooth1, genlayersmooth); // Новый генератор рек
        GenLayer genlayer3 = new GenLayerVoronoiZoom(10L, genlayerrivermix);
        genlayerrivermix.initWorldGenSeed(seed);
        genlayer3.initWorldGenSeed(seed);
        return new GenLayer[] { genlayerrivermix, genlayer3, genlayerrivermix };
    }
}
Теперь откроем класс GenLayerShore и найдем последнюю проверку:
Java:
if (k != Biome.getIdForBiome(Biomes.OCEAN) && k != Biome.getIdForBiome(Biomes.DEEP_OCEAN) && k != Biome.getIdForBiome(Biomes.RIVER) && k != Biome.getIdForBiome(Biomes.SWAMPLAND)) {
    int l1 = aint[j + 1 + (i + 0) * (areaWidth + 2)];
    int k2 = aint[j + 2 + (i + 1) * (areaWidth + 2)];
    int j3 = aint[j + 0 + (i + 1) * (areaWidth + 2)];
    int i4 = aint[j + 1 + (i + 2) * (areaWidth + 2)];

    if (!isBiomeOceanic(l1) && !isBiomeOceanic(k2) && !isBiomeOceanic(j3) && !isBiomeOceanic(i4)) {
        aint1[j + i * areaWidth] = k;
    } else {
        aint1[j + i * areaWidth] = Biome.getIdForBiome(Biomes.BEACH);
    }
} else {
    aint1[j + i * areaWidth] = k;
}
Добавим генерацию собственной границы:
Java:
if (k != Biome.getIdForBiome(Biomes.OCEAN) && k != Biome.getIdForBiome(Biomes.DEEP_OCEAN) && k != Biome.getIdForBiome(Biomes.RIVER) && k != Biome.getIdForBiome(Biomes.SWAMPLAND)) {
    if (!BiomeDictionary.hasType(Biome.getBiomeForId(k), BiomeInit.LAPIS)) {
        int l1 = aint[j + 1 + (i + 0) * (areaWidth + 2)];
        int k2 = aint[j + 2 + (i + 1) * (areaWidth + 2)];
        int j3 = aint[j + 0 + (i + 1) * (areaWidth + 2)];
        int i4 = aint[j + 1 + (i + 2) * (areaWidth + 2)];

        if (!isBiomeOceanic(l1) && !isBiomeOceanic(k2) && !isBiomeOceanic(j3) && !isBiomeOceanic(i4)) {
            aint1[j + i * areaWidth] = k;
        } else {
            aint1[j + i * areaWidth] = Biome.getIdForBiome(Biomes.BEACH);
        }
    } else { // Данный код выполняется для наших биомов, которым нужна граница
        int l1 = aint[j + 1 + (i + 0) * (areaWidth + 2)];
        int i1 = aint[j + 2 + (i + 1) * (areaWidth + 2)];
        int j1 = aint[j + 0 + (i + 1) * (areaWidth + 2)];
        int k1 = aint[j + 1 + (i + 2) * (areaWidth + 2)];

        if (isLapis(l1) && isLapis(i1) && isLapis(j1) && isLapis(k1)) {
            aint1[j + i * areaWidth] = k;
        } else {
            aint1[j + i * areaWidth] = Biome.getIdForBiome(BiomeInit.LAPISLAND_EDGE);
        }
    }
} else {
    aint1[j + i * areaWidth] = k;
}
И метод для проверки биомов:
Java:
/**
* Возвращает true, если биом наследуется от BiomeLapis
*/
private boolean isLapis(int biomeIDA) {
    return Biome.getBiome(biomeIDA) instanceof BiomeLapis;
}
В итоге получится GenLayerShoreCustom:
Java:
package ddooss.world.gen.layer;

import ddooss.init.BiomeInit;
import ddooss.world.biome.BiomeLapis;
import net.minecraft.init.Biomes;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.BiomeJungle;
import net.minecraft.world.biome.BiomeMesa;
import net.minecraft.world.gen.layer.GenLayer;
import net.minecraft.world.gen.layer.IntCache;

public class GenLayerShoreCustom extends GenLayer {
    public GenLayerShoreCustom(long seed, GenLayer parent) {
        super(seed);
        this.parent = parent;
    }

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight) {
        int[] aint = this.parent.getInts(areaX - 1, areaY - 1, areaWidth + 2, areaHeight + 2);
        int[] aint1 = IntCache.getIntCache(areaWidth * areaHeight);

        for (int i = 0; i < areaHeight; ++i) {
            for (int j = 0; j < areaWidth; ++j) {
                this.initChunkSeed((long) (j + areaX), (long) (i + areaY));
                int k = aint[j + 1 + (i + 1) * (areaWidth + 2)];
                Biome biome = Biome.getBiome(k);

                if (k == Biome.getIdForBiome(Biomes.MUSHROOM_ISLAND)) {
                    int j2 = aint[j + 1 + (i + 0) * (areaWidth + 2)];
                    int i3 = aint[j + 2 + (i + 1) * (areaWidth + 2)];
                    int l3 = aint[j + 0 + (i + 1) * (areaWidth + 2)];
                    int k4 = aint[j + 1 + (i + 2) * (areaWidth + 2)];

                    if (j2 != Biome.getIdForBiome(Biomes.OCEAN) && i3 != Biome.getIdForBiome(Biomes.OCEAN) && l3 != Biome.getIdForBiome(Biomes.OCEAN) && k4 != Biome.getIdForBiome(Biomes.OCEAN)) {
                        aint1[j + i * areaWidth] = k;
                    } else {
                        aint1[j + i * areaWidth] = Biome.getIdForBiome(Biomes.MUSHROOM_ISLAND_SHORE);
                    }
                } else if (biome != null && biome.getBiomeClass() == BiomeJungle.class) {
                    int i2 = aint[j + 1 + (i + 0) * (areaWidth + 2)];
                    int l2 = aint[j + 2 + (i + 1) * (areaWidth + 2)];
                    int k3 = aint[j + 0 + (i + 1) * (areaWidth + 2)];
                    int j4 = aint[j + 1 + (i + 2) * (areaWidth + 2)];

                    if (this.isJungleCompatible(i2) && this.isJungleCompatible(l2) && this.isJungleCompatible(k3) && this.isJungleCompatible(j4)) {
                        if (!isBiomeOceanic(i2) && !isBiomeOceanic(l2) && !isBiomeOceanic(k3) && !isBiomeOceanic(j4)) {
                            aint1[j + i * areaWidth] = k;
                        } else {
                            aint1[j + i * areaWidth] = Biome.getIdForBiome(Biomes.BEACH);
                        }
                    } else {
                        aint1[j + i * areaWidth] = Biome.getIdForBiome(Biomes.JUNGLE_EDGE);
                    }
                } else if (k != Biome.getIdForBiome(Biomes.EXTREME_HILLS) && k != Biome.getIdForBiome(Biomes.EXTREME_HILLS_WITH_TREES) && k != Biome.getIdForBiome(Biomes.EXTREME_HILLS_EDGE)) {
                    if (biome != null && biome.isSnowyBiome()) {
                        this.replaceIfNeighborOcean(aint, aint1, j, i, areaWidth, k, Biome.getIdForBiome(Biomes.COLD_BEACH));
                    } else if (k != Biome.getIdForBiome(Biomes.MESA) && k != Biome.getIdForBiome(Biomes.MESA_ROCK)) {
                        if (k != Biome.getIdForBiome(Biomes.OCEAN) && k != Biome.getIdForBiome(Biomes.DEEP_OCEAN) && k != Biome.getIdForBiome(Biomes.RIVER) && k != Biome.getIdForBiome(Biomes.SWAMPLAND)) {
                            if (!BiomeDictionary.hasType(Biome.getBiomeForId(k), BiomeInit.LAPIS)) {
                                int l1 = aint[j + 1 + (i + 0) * (areaWidth + 2)];
                                int k2 = aint[j + 2 + (i + 1) * (areaWidth + 2)];
                                int j3 = aint[j + 0 + (i + 1) * (areaWidth + 2)];
                                int i4 = aint[j + 1 + (i + 2) * (areaWidth + 2)];

                                if (!isBiomeOceanic(l1) && !isBiomeOceanic(k2) && !isBiomeOceanic(j3) && !isBiomeOceanic(i4)) {
                                    aint1[j + i * areaWidth] = k;
                                } else {
                                    aint1[j + i * areaWidth] = Biome.getIdForBiome(Biomes.BEACH);
                                }
                            } else { // Данный код выполняется для наших биомов, которым нужна граница
                                int l1 = aint[j + 1 + (i + 0) * (areaWidth + 2)];
                                int i1 = aint[j + 2 + (i + 1) * (areaWidth + 2)];
                                int j1 = aint[j + 0 + (i + 1) * (areaWidth + 2)];
                                int k1 = aint[j + 1 + (i + 2) * (areaWidth + 2)];

                                if (isLapis(l1) && isLapis(i1) && isLapis(j1) && isLapis(k1)) {
                                    aint1[j + i * areaWidth] = k;
                                } else {
                                    aint1[j + i * areaWidth] = Biome.getIdForBiome(BiomeInit.LAPISLAND_EDGE);
                                }
                            }
                        } else {
                            aint1[j + i * areaWidth] = k;
                        }
                    } else {
                        int l1 = aint[j + 1 + (i + 0) * (areaWidth + 2)];
                        int i1 = aint[j + 2 + (i + 1) * (areaWidth + 2)];
                        int j1 = aint[j + 0 + (i + 1) * (areaWidth + 2)];
                        int k1 = aint[j + 1 + (i + 2) * (areaWidth + 2)];

                        if (!isBiomeOceanic(l1) && !isBiomeOceanic(i1) && !isBiomeOceanic(j1) && !isBiomeOceanic(k1)) {
                            if (this.isMesa(l1) && this.isMesa(i1) && this.isMesa(j1) && this.isMesa(k1)) {
                                aint1[j + i * areaWidth] = k;
                            } else {
                                aint1[j + i * areaWidth] = Biome.getIdForBiome(Biomes.DESERT);
                            }
                        } else {
                            aint1[j + i * areaWidth] = k;
                        }
                    }
                } else {
                    this.replaceIfNeighborOcean(aint, aint1, j, i, areaWidth, k, Biome.getIdForBiome(Biomes.STONE_BEACH));
                }
            }
        }

        return aint1;
    }

    private void replaceIfNeighborOcean(int[] aint, int[] aint1, int j, int i, int areaWidth, int k, int biomeIDA) {
        if (isBiomeOceanic(k)) {
            aint1[j + i * areaWidth] = k;
        } else {
            int i1 = aint[j + 1 + (i + 0) * (areaWidth + 2)];
            int j1 = aint[j + 2 + (i + 1) * (areaWidth + 2)];
            int k1 = aint[j + 0 + (i + 1) * (areaWidth + 2)];
            int l1 = aint[j + 1 + (i + 2) * (areaWidth + 2)];

            if (!isBiomeOceanic(i1) && !isBiomeOceanic(j1) && !isBiomeOceanic(k1) && !isBiomeOceanic(l1)) {
                aint1[j + i * areaWidth] = k;
            } else {
                aint1[j + i * areaWidth] = biomeIDA;
            }
        }
    }

    private boolean isJungleCompatible(int biomeIDA) {
        if (Biome.getBiome(biomeIDA) != null && Biome.getBiome(biomeIDA).getBiomeClass() == BiomeJungle.class) {
            return true;
        } else {
            return biomeIDA == Biome.getIdForBiome(Biomes.JUNGLE_EDGE) || biomeIDA == Biome.getIdForBiome(Biomes.JUNGLE) || biomeIDA == Biome.getIdForBiome(Biomes.JUNGLE_HILLS) || biomeIDA == Biome.getIdForBiome(Biomes.FOREST) || biomeIDA == Biome.getIdForBiome(Biomes.TAIGA) || isBiomeOceanic(biomeIDA);
        }
    }

    private boolean isMesa(int biomeIDA) {
        return Biome.getBiome(biomeIDA) instanceof BiomeMesa;
    }

    /**
     * Возвращает true, если биом наследуется от BiomeLapis
     */
    private boolean isLapis(int biomeIDA) {
        return Biome.getBiome(biomeIDA) instanceof BiomeLapis;
    }
}
Аналогично открываем класс GenLayerRiverMix и находим проверку океанов:
Java:
if (aint[i] != Biome.getIdForBiome(Biomes.OCEAN) && aint[i] != Biome.getIdForBiome(Biomes.DEEP_OCEAN)) {

}
И добавляем сюда свою проверку, чтобы в наших биомах небыло рек:
Java:
if (aint[i] != Biome.getIdForBiome(Biomes.OCEAN) && aint[i] != Biome.getIdForBiome(Biomes.DEEP_OCEAN) && !BiomeDictionary.hasType(Biome.getBiomeForId(aint[i]), BiomeInit.LAPIS)) { // Добавляем проверку для наших биомов

}
Получается класс GenLayerRiverMixCustom:
Java:
package ddooss.world.gen.layer;

import ddooss.init.BiomeInit;
import net.minecraft.init.Biomes;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.layer.GenLayer;
import net.minecraft.world.gen.layer.IntCache;
import net.minecraftforge.common.BiomeDictionary;

public class GenLayerRiverMixCustom extends GenLayer {
    private final GenLayer biomePatternGeneratorChain;
    private final GenLayer riverPatternGeneratorChain;

    public GenLayerRiverMixCustom(long seed, GenLayer biome, GenLayer river) {
        super(seed);
        this.biomePatternGeneratorChain = biome;
        this.riverPatternGeneratorChain = river;
    }

    public void initWorldGenSeed(long seed) {
        this.biomePatternGeneratorChain.initWorldGenSeed(seed);
        this.riverPatternGeneratorChain.initWorldGenSeed(seed);
        super.initWorldGenSeed(seed);
    }

    public int[] getInts(int areaX, int areaY, int areaWidth, int areaHeight) {
        int[] aint = this.biomePatternGeneratorChain.getInts(areaX, areaY, areaWidth, areaHeight);
        int[] aint1 = this.riverPatternGeneratorChain.getInts(areaX, areaY, areaWidth, areaHeight);
        int[] aint2 = IntCache.getIntCache(areaWidth * areaHeight);

        for (int i = 0; i < areaWidth * areaHeight; ++i) {
            if (aint[i] != Biome.getIdForBiome(Biomes.OCEAN) && aint[i] != Biome.getIdForBiome(Biomes.DEEP_OCEAN) && !BiomeDictionary.hasType(Biome.getBiomeForId(aint[i]), BiomeInit.LAPIS)) { // Добавляем проверку для наших биомов
                if (aint1[i] == Biome.getIdForBiome(Biomes.RIVER)) {
                    if (aint[i] == Biome.getIdForBiome(Biomes.ICE_PLAINS)) {
                        aint2[i] = Biome.getIdForBiome(Biomes.FROZEN_RIVER);
                    } else if (aint[i] != Biome.getIdForBiome(Biomes.MUSHROOM_ISLAND) && aint[i] != Biome.getIdForBiome(Biomes.MUSHROOM_ISLAND_SHORE)) {
                        aint2[i] = aint1[i] & 255;
                    } else {
                        aint2[i] = Biome.getIdForBiome(Biomes.MUSHROOM_ISLAND_SHORE);
                    }
                } else {
                    aint2[i] = aint[i];
                }
            } else {
                aint2[i] = aint[i];
            }
        }

        return aint2;
    }
}
Теперь наши биомы имеют границу.
2018-07-31_12.06.02.png
  • 6_GenLayerAddIsland.png
    6_GenLayerAddIsland.png
    567 байт · Просмотры: 2,093
Автор
yoloven
Скачивания
13
Просмотры
10,566
Первый выпуск
Обновление
Оценка
5.00 звёзд 4 оценок

Другие ресурсы пользователя yoloven

Последние обновления

  1. Исправления

    1. Добавил содержание руководства 2. Исправил некоторые картинки в GenLayer/SUNFLOWERS. 3...
Сверху