com.kegare.caveworld.world.ChunkProviderDeepCaveworld.java Source code

Java tutorial

Introduction

Here is the source code for com.kegare.caveworld.world.ChunkProviderDeepCaveworld.java

Source

/*
 * Caveworld
 *
 * Copyright (c) 2014 kegare
 * https://github.com/kegare
 *
 * This mod is distributed under the terms of the Minecraft Mod Public License Japanese Translation, or MMPL_J.
 */

package com.kegare.caveworld.world;

import java.util.Arrays;
import java.util.List;
import java.util.Random;

import net.minecraft.block.Block;
import net.minecraft.block.BlockFalling;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.init.Blocks;
import net.minecraft.util.IProgressUpdate;
import net.minecraft.util.MathHelper;
import net.minecraft.world.ChunkPosition;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeDecorator;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.MapGenBase;
import net.minecraft.world.gen.feature.WorldGenLakes;
import net.minecraft.world.gen.feature.WorldGenLiquids;
import net.minecraft.world.gen.feature.WorldGenVines;
import net.minecraft.world.gen.feature.WorldGenerator;
import net.minecraftforge.common.BiomeDictionary;
import net.minecraftforge.common.BiomeDictionary.Type;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.terraingen.DecorateBiomeEvent;
import net.minecraftforge.event.terraingen.DecorateBiomeEvent.Decorate;
import net.minecraftforge.event.terraingen.OreGenEvent;
import net.minecraftforge.event.terraingen.PopulateChunkEvent;
import net.minecraftforge.event.terraingen.PopulateChunkEvent.Populate.EventType;
import net.minecraftforge.event.terraingen.TerrainGen;

import org.apache.commons.lang3.ArrayUtils;

import com.bioxx.tfc.Chunkdata.ChunkData;
import com.bioxx.tfc.Core.TFC_Core;
import com.bioxx.tfc.WorldGen.DataLayer;
import com.kegare.caveworld.api.BlockEntry;
import com.kegare.caveworld.api.CaveworldAPI;
import com.kegare.caveworld.api.ICaveBiome;
import com.kegare.caveworld.api.ICaveVein;
import com.kegare.caveworld.core.Config;
import com.kegare.caveworld.world.gen.MapGenDeepCaves;
import com.kegare.caveworld.world.gen.MapGenUnderCaves;

import cpw.mods.fml.common.Optional.Method;

public class ChunkProviderDeepCaveworld implements IChunkProvider {
    private final World worldObj;
    private final Random random;

    private final MapGenBase caveGenerator = new MapGenDeepCaves();
    private final MapGenBase underCaveGenerator = new MapGenUnderCaves();

    private final WorldGenerator lakeWaterGen = new WorldGenLakes(Blocks.water);
    private final WorldGenerator lakeLavaGen = new WorldGenLakes(Blocks.lava);
    private final WorldGenerator liquidWaterGen = new WorldGenLiquids(Blocks.flowing_water);
    private final WorldGenerator liquidLavaGen = new WorldGenLiquids(Blocks.flowing_lava);
    private final WorldGenerator vinesGen = new WorldGenVines();

    public ChunkProviderDeepCaveworld(World world) {
        this.worldObj = world;
        this.random = new Random(world.getSeed());
    }

    @Override
    public Chunk provideChunk(int chunkX, int chunkZ) {
        random.setSeed(chunkX * 341873128712L + chunkZ * 132897987541L);

        int worldHeight = worldObj.provider.getActualHeight();
        BiomeGenBase biome = worldObj.getWorldChunkManager().getBiomeGenAt(chunkX * 16, chunkZ * 16);
        Block[] blocks = new Block[65536];
        byte[] metadata = new byte[65536];
        ICaveBiome entry = CaveworldAPI.getCaveBiome(biome);
        Block block = entry.getTerrainBlock().getBlock();
        int meta = entry.getTerrainBlock().getMetadata();

        Arrays.fill(blocks, block);
        Arrays.fill(metadata, (byte) meta);

        if (Config.generateDeepCaves) {
            caveGenerator.func_151539_a(this, worldObj, chunkX, chunkZ, blocks);
        }

        if (Config.generateUnderCaves) {
            underCaveGenerator.func_151539_a(this, worldObj, chunkX, chunkZ, blocks);
        }

        int i;
        boolean flag = random.nextInt(100) == 0;

        for (int x = 0; x < 16; ++x) {
            for (int z = 0; z < 16; ++z) {
                i = (x * 16 + z) * 256;

                blocks[i] = Blocks.bedrock;
                blocks[i + worldHeight - 1] = block;

                if (!entry.getTerrainBlock().equals(entry.getTopBlock())) {
                    for (int y = 1; y < worldHeight - 2; ++y) {
                        if (blocks[i + y] != null) {
                            if (blocks[i + y + 1] == null) {
                                blocks[i + y] = entry.getTopBlock().getBlock();
                                metadata[i + y] = (byte) entry.getTopBlock().getMetadata();
                            } else if (blocks[i + y - 1] == null && flag && random.nextInt(30) == 0) {
                                blocks[i + y] = Blocks.web;
                                metadata[i + y] = 0;
                            }
                        }
                    }
                }

                for (int y = 255; y >= worldHeight; --y) {
                    blocks[i + y] = null;
                }
            }
        }

        for (i = 0; meta != 0 && i < blocks.length; ++i) {
            if (blocks[i] != block) {
                metadata[i] = 0;
            }
        }

        Chunk chunk = new Chunk(worldObj, blocks, metadata, chunkX, chunkZ);
        byte[] biomes = new byte[256];

        Arrays.fill(biomes, (byte) biome.biomeID);

        chunk.setBiomeArray(biomes);
        chunk.resetRelightChecks();

        try {
            provideChunkTFC(chunk);
        } catch (NoSuchMethodError e) {
        }

        return chunk;
    }

    @Method(modid = "terrafirmacraft")
    private void provideChunkTFC(Chunk chunk) {
        ChunkData data = new ChunkData() {
            @Override
            public float getRainfall(int x, int z) {
                return 0.0F;
            };
        }.CreateNew(worldObj, chunk.xPosition, chunk.zPosition);

        data.heightmap = chunk.heightMap;
        Arrays.fill(data.rainfallMap, DataLayer.NoTree);

        TFC_Core.getCDM(worldObj).addData(chunk, data);
    }

    @Override
    public Chunk loadChunk(int chunkX, int chunkZ) {
        return provideChunk(chunkX, chunkZ);
    }

    @Override
    public void populate(IChunkProvider chunkProvider, int chunkX, int chunkZ) {
        BlockFalling.fallInstantly = true;

        int worldX = chunkX * 16;
        int worldZ = chunkZ * 16;
        BiomeGenBase biome = worldObj.getBiomeGenForCoords(worldX, worldZ);
        BiomeDecorator decorator = biome.theBiomeDecorator;
        int worldHeight = worldObj.provider.getActualHeight();
        long worldSeed = worldObj.getSeed();
        random.setSeed(worldSeed);
        long xSeed = random.nextLong() >> 2 + 1L;
        long zSeed = random.nextLong() >> 2 + 1L;
        random.setSeed(chunkX * xSeed + chunkZ * zSeed ^ worldSeed);

        MinecraftForge.EVENT_BUS
                .post(new PopulateChunkEvent.Pre(chunkProvider, worldObj, random, chunkX, chunkZ, false));

        int i, x, y, z;

        if (BiomeDictionary.isBiomeOfType(biome, Type.NETHER)) {
            if (Config.generateLakes && random.nextInt(8) == 0 && TerrainGen.populate(chunkProvider, worldObj,
                    random, chunkX, chunkZ, false, EventType.LAVA)) {
                x = worldX + random.nextInt(16) + 8;
                y = random.nextInt(worldHeight - 16);
                z = worldZ + random.nextInt(16) + 8;

                lakeLavaGen.generate(worldObj, random, x, y, z);
            }
        } else if (!BiomeDictionary.isBiomeOfType(biome, Type.END)) {
            if (Config.generateLakes) {
                if (!BiomeDictionary.isBiomeOfType(biome, Type.SANDY) && random.nextInt(8) == 0 && TerrainGen
                        .populate(chunkProvider, worldObj, random, chunkX, chunkZ, false, EventType.LAKE)) {
                    x = worldX + random.nextInt(16) + 8;
                    y = random.nextInt(worldHeight - 16);
                    z = worldZ + random.nextInt(16) + 8;

                    lakeWaterGen.generate(worldObj, random, x, y, z);
                }

                if (random.nextInt(50) == 0 && TerrainGen.populate(chunkProvider, worldObj, random, chunkX, chunkZ,
                        false, EventType.LAVA)) {
                    x = worldX + random.nextInt(16) + 8;
                    y = random.nextInt(worldHeight / 2);
                    z = worldZ + random.nextInt(16) + 8;

                    lakeLavaGen.generate(worldObj, random, x, y, z);
                }
            }
        } else if (random.nextInt(4) == 0) {
            x = worldX + random.nextInt(16) + 8;
            y = random.nextInt(worldHeight - 16);
            z = worldZ + random.nextInt(16) + 8;

            lakeWaterGen.generate(worldObj, random, x, y, z);
        }

        MinecraftForge.ORE_GEN_BUS.post(new OreGenEvent.Pre(worldObj, random, worldX, worldZ));

        for (ICaveVein vein : CaveworldAPI.getCaveVeins()) {
            generateVein(vein, worldX, worldZ, 16, worldHeight - 1, Math.max(vein.getGenBlockCount() / 3, 1), 0);
            generateVein(vein, worldX, worldZ, 1, 15, 0, Math.max(vein.getGenWeight() / 3, 1));
        }

        MinecraftForge.ORE_GEN_BUS.post(new OreGenEvent.Post(worldObj, random, worldX, worldZ));
        MinecraftForge.EVENT_BUS.post(new DecorateBiomeEvent.Pre(worldObj, random, worldX, worldZ));

        if (decorator.generateLakes
                && TerrainGen.decorate(worldObj, random, worldX, worldZ, Decorate.EventType.LAKE)) {
            if (BiomeDictionary.isBiomeOfType(biome, Type.NETHER)) {
                for (i = 0; i < 40; ++i) {
                    x = worldX + random.nextInt(16) + 8;
                    y = random.nextInt(worldHeight - 12) + 10;
                    z = worldZ + random.nextInt(16) + 8;

                    liquidLavaGen.generate(worldObj, random, x, y, z);
                }
            } else if (BiomeDictionary.isBiomeOfType(biome, Type.WATER)) {
                for (i = 0; i < 65; ++i) {
                    x = worldX + random.nextInt(16) + 8;
                    y = random.nextInt(random.nextInt(worldHeight - 16) + 10);
                    z = worldZ + random.nextInt(16) + 8;

                    liquidWaterGen.generate(worldObj, random, x, y, z);
                }
            } else if (!BiomeDictionary.isBiomeOfType(biome, Type.END)) {
                for (i = 0; i < 50; ++i) {
                    x = worldX + random.nextInt(16) + 8;
                    y = random.nextInt(random.nextInt(worldHeight - 16) + 10);
                    z = worldZ + random.nextInt(16) + 8;

                    liquidWaterGen.generate(worldObj, random, x, y, z);
                }

                for (i = 0; i < 20; ++i) {
                    x = worldX + random.nextInt(16) + 8;
                    y = random.nextInt(worldHeight / 2);
                    z = worldZ + random.nextInt(16) + 8;

                    liquidLavaGen.generate(worldObj, random, x, y, z);
                }
            }
        }

        if (Config.decorateVines && (BiomeDictionary.isBiomeOfType(biome, Type.FOREST)
                || BiomeDictionary.isBiomeOfType(biome, Type.MOUNTAIN)) && random.nextInt(10) == 0) {
            for (i = 0; i < 30; ++i) {
                x = worldX + random.nextInt(16) + 8;
                y = random.nextInt(worldHeight - 40) + 40;
                z = worldZ + random.nextInt(16) + 8;

                vinesGen.generate(worldObj, random, x, y, z);
            }
        }

        MinecraftForge.EVENT_BUS.post(new DecorateBiomeEvent.Post(worldObj, random, worldX, worldZ));
        MinecraftForge.EVENT_BUS
                .post(new PopulateChunkEvent.Post(chunkProvider, worldObj, random, chunkX, chunkZ, false));

        BlockFalling.fallInstantly = false;
    }

    private void generateVein(ICaveVein vein, int worldX, int worldZ, int min, int max, int countBonus,
            int weightBonus) {
        int worldHeight = worldObj.getActualHeight();
        BlockEntry block = vein.getBlock();
        int count = vein.getGenBlockCount() + countBonus;
        int weight = vein.getGenWeight() * 2 + weightBonus;
        int rate = vein.getGenRate();
        BlockEntry target = vein.getGenTargetBlock();
        int[] biomes = vein.getGenBiomes();

        if (weight > 0) {
            for (int i = 0; i < weight; ++i) {
                if (random.nextInt(100) + 1 > rate) {
                    continue;
                }

                int x = worldX + random.nextInt(16);
                int y = random.nextInt(Math.min(max, worldHeight - 1) - min) + min;
                int z = worldZ + random.nextInt(16);
                float var1 = random.nextFloat() * (float) Math.PI;
                double var2 = x + 8 + MathHelper.sin(var1) * count / 8.0F;
                double var3 = x + 8 - MathHelper.sin(var1) * count / 8.0F;
                double var4 = z + 8 + MathHelper.cos(var1) * count / 8.0F;
                double var5 = z + 8 - MathHelper.cos(var1) * count / 8.0F;
                double var6 = y + random.nextInt(3) - 2;
                double var7 = y + random.nextInt(3) - 2;
                int gen = 0;

                for (int j = 0; gen <= count && j <= count; ++j) {
                    double var8 = var2 + (var3 - var2) * j / count;
                    double var9 = var6 + (var7 - var6) * j / count;
                    double var10 = var4 + (var5 - var4) * j / count;
                    double var11 = random.nextDouble() * count / 16.0D;
                    double var12 = (MathHelper.sin(j * (float) Math.PI / count) + 1.0F) * var11 + 1.0D;
                    double var13 = (MathHelper.sin(j * (float) Math.PI / count) + 1.0F) * var11 + 1.0D;

                    for (x = MathHelper.floor_double(var8 - var12 / 2.0D); gen <= count
                            && x <= MathHelper.floor_double(var8 + var12 / 2.0D); ++x) {
                        double xScale = (x + 0.5D - var8) / (var12 / 2.0D);

                        if (xScale * xScale < 1.0D) {
                            for (y = MathHelper.floor_double(var9 - var13 / 2.0D); gen <= count
                                    && y <= MathHelper.floor_double(var9 + var13 / 2.0D); ++y) {
                                double yScale = (y + 0.5D - var9) / (var13 / 2.0D);

                                if (xScale * xScale + yScale * yScale < 1.0D) {
                                    for (z = MathHelper.floor_double(var10 - var12 / 2.0D); z <= MathHelper
                                            .floor_double(var10 + var12 / 2.0D); ++z) {
                                        double zScale = (z + 0.5D - var10) / (var12 / 2.0D);

                                        if (xScale * xScale + yScale * yScale + zScale * zScale < 1.0D) {
                                            if (target == null) {
                                                if (!worldObj.getBlock(x, y, z).isReplaceableOreGen(worldObj, x, y,
                                                        z, Blocks.stone)) {
                                                    continue;
                                                }
                                            } else if (!worldObj.getBlock(x, y, z).isReplaceableOreGen(worldObj, x,
                                                    y, z, target.getBlock())
                                                    || worldObj.getBlockMetadata(x, y, z) != target.getMetadata()) {
                                                continue;
                                            }

                                            if (biomes == null || biomes.length <= 0 || ArrayUtils.contains(biomes,
                                                    worldObj.getBiomeGenForCoords(x, z).biomeID)) {
                                                if (worldObj.setBlock(x, y, z, block.getBlock(),
                                                        block.getMetadata(), 2)) {
                                                    ++gen;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    @Override
    public boolean chunkExists(int chunkX, int chunkZ) {
        return true;
    }

    @Override
    public boolean saveChunks(boolean flag, IProgressUpdate progress) {
        return true;
    }

    @Override
    public void saveExtraData() {
    }

    @Override
    public boolean unloadQueuedChunks() {
        return false;
    }

    @Override
    public boolean canSave() {
        return true;
    }

    @Override
    public String makeString() {
        return "CaveworldRandomLevelSource";
    }

    @Override
    public List getPossibleCreatures(EnumCreatureType creature, int x, int y, int z) {
        if (y <= 0 || y >= worldObj.getActualHeight() || creature == EnumCreatureType.monster && y < 64) {
            return null;
        }

        BiomeGenBase biome = worldObj.getBiomeGenForCoords(x, z);

        return biome == null ? null : biome.getSpawnableList(creature);
    }

    @Override
    public ChunkPosition func_147416_a(World world, String name, int x, int y, int z) {
        return null;
    }

    @Override
    public int getLoadedChunkCount() {
        return 0;
    }

    @Override
    public void recreateStructures(int chunkX, int chunkZ) {
    }
}