001/*
002 * Trident - A Multithreaded Server Alternative
003 * Copyright 2014 The TridentSDK Team
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package net.tridentsdk.server.world.gen;
019
020import net.tridentsdk.base.Substance;
021import net.tridentsdk.concurrent.SelectableThreadPool;
022import net.tridentsdk.server.concurrent.ThreadsHandler;
023import net.tridentsdk.server.world.ChunkSection;
024import net.tridentsdk.server.world.WorldUtils;
025import net.tridentsdk.util.TridentLogger;
026import net.tridentsdk.world.ChunkLocation;
027import net.tridentsdk.world.gen.ChunkGenerator;
028
029import java.util.concurrent.CountDownLatch;
030import java.util.concurrent.atomic.AtomicReferenceArray;
031
032/**
033 * Default world generator engine for Trident
034 *
035 * @author The TridentSDK Team
036 */
037public class DefaultWorldGen extends ChunkGenerator {
038    private final SimplexOctaveGenerator generator = new SimplexOctaveGenerator(12, 0.5, (int) seed);
039    private final SelectableThreadPool executor = ThreadsHandler.genExecutor();
040
041    public DefaultWorldGen(long seed) {
042        super(seed);
043    }
044
045    @Override
046    public char[][] generateBlocks(final ChunkLocation location, AtomicReferenceArray<Integer> heights) {
047        final char[][] data = new char[16][ChunkSection.LENGTH];
048        final CountDownLatch release = new CountDownLatch(16);
049
050        for (int x = 0; x < 16; x++) {
051            final int finalX = x;
052
053            executor.execute(() -> {
054                for (int z = 0; z < 16; z++) {
055                    final int i = WorldUtils.intScale(0, 140, generator.noise(finalX + (location.x() << 4), z + (location.z() << 4))) - 20;
056                    heights.set(WorldUtils.heightIndex(finalX, z), i);
057
058                    if (i < 40) {
059                        for (int j = i; j <= 40; j++) {
060                            data[j / 16][WorldUtils.blockArrayIndex(finalX, j % 16, z)] = Substance.WATER.asExtended();
061                        }
062                    }
063
064                    for (int y = 0; y <= i; y++) {
065                        if (i < 40) {
066                            if (y == i) {
067                                data[y / 16][WorldUtils.blockArrayIndex(finalX, y % 16, z)] = Substance.SAND.asExtended();
068                                continue;
069                            }
070                        }
071
072                        if (y == i) {
073                            data[y / 16][WorldUtils.blockArrayIndex(finalX, i % 16, z)] = Substance.GRASS.asExtended();
074                        } else
075                            data[y / 16][WorldUtils.blockArrayIndex(finalX, y % 16, z)] = Substance.DIRT.asExtended();
076                    }
077                }
078
079                release.countDown();
080            });
081        }
082
083        try {
084            release.await();
085        } catch (InterruptedException e) {
086            TridentLogger.get().error(e);
087            return null;
088        }
089
090        return data;
091    }
092
093    @Override
094    public byte[][] generateData(ChunkLocation location) {
095        return new byte[0][];
096    }
097}