All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.nukkit.level.generator.TheEnd Maven / Gradle / Ivy

There is a newer version: 1.20.40-r1
Show newest version
package cn.nukkit.level.generator;

import cn.nukkit.api.Since;
import cn.nukkit.blockstate.BlockState;
import cn.nukkit.level.ChunkManager;
import cn.nukkit.level.Level;
import cn.nukkit.level.biome.Biome;
import cn.nukkit.level.biome.EnumBiome;
import cn.nukkit.level.format.generic.BaseFullChunk;
import cn.nukkit.level.generator.noise.vanilla.d.NoiseGeneratorOctavesD;
import cn.nukkit.level.generator.noise.vanilla.d.NoiseGeneratorSimplexD;
import cn.nukkit.level.generator.populator.impl.PopulatorChorusTree;
import cn.nukkit.level.generator.populator.impl.PopulatorEndGateway;
import cn.nukkit.level.generator.populator.impl.PopulatorEndIsland;
import cn.nukkit.level.generator.populator.impl.PopulatorEndObsidianPillar;
import cn.nukkit.level.generator.populator.type.Populator;
import cn.nukkit.math.MathHelper;
import cn.nukkit.math.NukkitMath;
import cn.nukkit.math.NukkitRandom;
import cn.nukkit.math.Vector3;

import java.util.*;

/**
 * @author GoodLucky777
 * 

* This generator originally adapted from the Glowstone's * TheEndGenerator * (https://github.com/GlowstoneMC/Glowstone/blob/3de174426cd1e15e78050b9d691a3c1722c83181/src/main/java/net/glowstone/generator/TheEndGenerator.java) *

* Glowstone licensed under the following MIT license: *

* Glowstone Copyright (C) 2015-2020 The Glowstone Project. * Glowstone Copyright (C) 2011-2014 Tad Hardesty. * Lightstone Copyright (C) 2010-2011 Graham Edgecombe. *

* Permission is hereby granted, free of charge, to any person obtaining * a copy * of this software and associated documentation files (the "Software"), * to deal * in the Software without restriction, including without limitation the * rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: *

* The above copyright notice and this permission notice shall be * included in * all copies or substantial portions of the Software. *

* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT * SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN * THE SOFTWARE. */ public class TheEnd extends Generator { private static final BlockState STATE_END_STONE = BlockState.of(END_STONE); private static final double coordinateScale = 684.412; private static final double detailNoiseScaleX = 80; private static final double detailNoiseScaleZ = 80; private final double[][][] density = new double[3][3][33]; double[] detailNoise; double[] roughnessNoise; double[] roughnessNoise2; private ChunkManager level; private NukkitRandom nukkitRandom; private Random random; private NoiseGeneratorOctavesD roughnessNoiseOctaves; private NoiseGeneratorOctavesD roughnessNoiseOctaves2; private NoiseGeneratorOctavesD detailNoiseOctaves; private NoiseGeneratorSimplexD islandNoise; private final List populators = new ArrayList<>(); private final List generationPopulators = new ArrayList<>(); private long localSeed1; private long localSeed2; public TheEnd() { this(Collections.emptyMap()); } public TheEnd(Map options) { // Nothing here. Just used for future update. } @Override public int getId() { return Generator.TYPE_THE_END; } @Override public int getDimension() { return Level.DIMENSION_THE_END; } @Override public String getName() { return "the_end"; } @Override public Map getSettings() { return new HashMap<>(); } @Override public ChunkManager getChunkManager() { return this.level; } @Override public void init(ChunkManager level, NukkitRandom random) { this.level = level; this.nukkitRandom = random; this.random = new Random(); this.nukkitRandom.setSeed(this.level.getSeed()); this.localSeed1 = this.random.nextLong(); this.localSeed2 = this.random.nextLong(); this.roughnessNoiseOctaves = new NoiseGeneratorOctavesD(random, 16); this.roughnessNoiseOctaves2 = new NoiseGeneratorOctavesD(random, 16); this.detailNoiseOctaves = new NoiseGeneratorOctavesD(random, 8); this.islandNoise = new NoiseGeneratorSimplexD(random); this.populators.add(new PopulatorEndIsland(this)); this.populators.add(new PopulatorChorusTree(this)); this.populators.add(new PopulatorEndGateway(this)); PopulatorEndObsidianPillar.ObsidianPillar[] obsidianPillars = PopulatorEndObsidianPillar.ObsidianPillar.getObsidianPillars(this.level.getSeed()); for (PopulatorEndObsidianPillar.ObsidianPillar obsidianPillar : obsidianPillars) { PopulatorEndObsidianPillar populator = new PopulatorEndObsidianPillar(obsidianPillar); this.populators.add(populator); } } @Override public void generateChunk(int chunkX, int chunkZ) { int baseX = chunkX << 4; int baseZ = chunkZ << 4; this.nukkitRandom.setSeed(chunkX * localSeed1 ^ chunkZ * localSeed2 ^ this.level.getSeed()); BaseFullChunk chunk = level.getChunk(chunkX, chunkZ); for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { Biome biome = EnumBiome.THE_END.biome; chunk.setBiomeId(x, z, biome.getId()); } } int densityX = chunkX << 1; int densityZ = chunkZ << 1; this.detailNoise = this.detailNoiseOctaves.generateNoiseOctaves(this.detailNoise, densityX, 0, densityZ, 3, 33, 3, (coordinateScale * 2) / detailNoiseScaleX, 4.277575000000001, (coordinateScale * 2) / detailNoiseScaleZ); this.roughnessNoise = this.roughnessNoiseOctaves.generateNoiseOctaves(this.roughnessNoise, densityX, 0, densityZ, 3, 33, 3, coordinateScale * 2, coordinateScale, coordinateScale * 2); this.roughnessNoise2 = this.roughnessNoiseOctaves2.generateNoiseOctaves(this.roughnessNoise2, densityX, 0, densityZ, 3, 33, 3, coordinateScale * 2, coordinateScale, coordinateScale * 2); int index = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { float noiseHeight = this.getIslandHeight(chunkX, chunkZ, i, j); for (int k = 0; k < 33; k++) { double noiseR = this.roughnessNoise[index] / 512d; double noiseR2 = this.roughnessNoise2[index] / 512d; double noiseD = (this.detailNoise[index] / 10d + 1d) / 2d; // linear interpolation double dens = noiseD < 0 ? noiseR : noiseD > 1 ? noiseR2 : noiseR + (noiseR2 - noiseR) * noiseD; dens = (dens - 8d) + (double) noiseHeight; index++; double lowering; if (k < 8) { lowering = (float) (8 - k) / 7; dens = dens * (1d - lowering) + lowering * -30d; } else if (k > 33 / 2 - 2) { lowering = (float) (k - ((33 / 2) - 2)) / 64d; lowering = NukkitMath.clamp(lowering, 0, 1); dens = dens * (1d - lowering) + lowering * -3000d; } density[i][j][k] = dens; } } } for (int i = 0; i < 3 - 1; i++) { for (int j = 0; j < 3 - 1; j++) { for (int k = 0; k < 33 - 1; k++) { double d1 = density[i][j][k]; double d2 = density[i + 1][j][k]; double d3 = density[i][j + 1][k]; double d4 = density[i + 1][j + 1][k]; double d5 = (density[i][j][k + 1] - d1) / 4; double d6 = (density[i + 1][j][k + 1] - d2) / 4; double d7 = (density[i][j + 1][k + 1] - d3) / 4; double d8 = (density[i + 1][j + 1][k + 1] - d4) / 4; for (int l = 0; l < 4; l++) { double d9 = d1; double d10 = d3; for (int m = 0; m < 8; m++) { double dens = d9; for (int n = 0; n < 8; n++) { // any density > 0 is ground, any density <= 0 is air. if (dens > 0) { chunk.setBlockState(m + (i << 3), l + (k << 2), n + (j << 3), STATE_END_STONE); } // interpolation along z dens += (d10 - d9) / 8; } // interpolation along x d9 += (d2 - d1) / 8; // interpolate along z d10 += (d4 - d3) / 8; } // interpolation along y d1 += d5; d3 += d7; d2 += d6; d4 += d8; } } } } for (Populator populator : this.generationPopulators) { populator.populate(this.level, chunkX, chunkZ, this.nukkitRandom, chunk); } } @Override public void populateChunk(int chunkX, int chunkZ) { BaseFullChunk chunk = level.getChunk(chunkX, chunkZ); this.nukkitRandom.setSeed(0xdeadbeef ^ ((long) chunkX << 8) ^ chunkZ ^ this.level.getSeed()); for (Populator populator : this.populators) { populator.populate(this.level, chunkX, chunkZ, this.nukkitRandom, chunk); } Biome biome = EnumBiome.getBiome(chunk.getBiomeId(7, 7)); biome.populateChunk(this.level, chunkX, chunkZ, this.nukkitRandom); } public Vector3 getSpawn() { return new Vector3(100, 49, 0); } public float getIslandHeight(int chunkX, int chunkZ, int x, int z) { float x1 = (float) (chunkX * 2 + x); float z1 = (float) (chunkZ * 2 + z); float islandHeight1 = NukkitMath.clamp(100f - MathHelper.sqrt((x1 * x1) + (z1 * z1)) * 8f, -100f, 80f); for (int i = -12; i <= 12; i++) { for (int j = -12; j <= 12; j++) { long x2 = chunkX + i; long z2 = chunkZ + j; if ((x2 * x2) + (z2 * z2) > 4096L && this.islandNoise.getValue((double) x2, (double) z2) < (double) -0.9f) { x1 = (float) (x - i * 2); z1 = (float) (z - j * 2); float islandHeight2 = 100f - MathHelper.sqrt((x1 * x1) + (z1 * z1)) * ((Math.abs((float) x2) * 3439f + Math.abs((float) z2) * 147f) % 13f + 9f); islandHeight2 = NukkitMath.clamp(islandHeight2, -100f, 80f); islandHeight1 = Math.max(islandHeight1, islandHeight2); } } } return islandHeight1; } @Since("1.19.21-r2") @Override public boolean shouldGenerateStructures() { return true; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy