Package com.sk89q.worldedit.regions.shape

Source Code of com.sk89q.worldedit.regions.shape.ArbitraryBiomeShape

/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.sk89q.worldedit.regions.shape;

import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.FlatRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.biome.BaseBiome;

/**
* Generates solid and hollow shapes according to materials returned by the
* {@link #getBiome} method.
*/
public abstract class ArbitraryBiomeShape {

    private final FlatRegion extent;
    private int cacheOffsetX;
    private int cacheOffsetZ;
    @SuppressWarnings("FieldCanBeLocal")
    private int cacheSizeX;
    private int cacheSizeZ;

    public ArbitraryBiomeShape(Region extent) {
        if (extent instanceof FlatRegion) {
            this.extent = (FlatRegion) extent;
        }
        else {
            // TODO: polygonize
            this.extent = new CuboidRegion(extent.getWorld(), extent.getMinimumPoint(), extent.getMaximumPoint());
        }

        Vector2D min = extent.getMinimumPoint().toVector2D();
        Vector2D max = extent.getMaximumPoint().toVector2D();

        cacheOffsetX = min.getBlockX() - 1;
        cacheOffsetZ = min.getBlockZ() - 1;

        cacheSizeX = (int) (max.getX() - cacheOffsetX + 2);
        cacheSizeZ = (int) (max.getZ() - cacheOffsetZ + 2);

        cache = new BaseBiome[cacheSizeX * cacheSizeZ];
    }

    protected Iterable<Vector2D> getExtent() {
        return extent.asFlatRegion();
    }


    /**
     * Cache entries:
     * null = unknown
     * OUTSIDE = outside
     * else = inside
     */
    private final BaseBiome[] cache;

    /**
     * Override this function to specify the shape to generate.
     *
     * @param x X coordinate to be queried
     * @param z Z coordinate to be queried
     * @param defaultBaseBiome The default biome for the current column.
     * @return material to place or null to not place anything.
     */
    protected abstract BaseBiome getBiome(int x, int z, BaseBiome defaultBaseBiome);

    private BaseBiome getBiomeCached(int x, int z, BaseBiome baseBiome) {
        final int index = (z - cacheOffsetZ) + (x - cacheOffsetX) * cacheSizeZ;

        final BaseBiome cacheEntry = cache[index];
        if (cacheEntry == null) {// unknown, fetch material
            final BaseBiome material = getBiome(x, z, baseBiome);
            if (material == null) {
                // outside
                cache[index] = OUTSIDE;
                return null;
            }

            cache[index] = material;
            return material;
        }

        if (cacheEntry == OUTSIDE) {
            // outside
            return null;
        }

        return cacheEntry;
    }

    private boolean isInsideCached(int x, int z, BaseBiome baseBiome) {
        final int index = (z - cacheOffsetZ) + (x - cacheOffsetX) * cacheSizeZ;

        final BaseBiome cacheEntry = cache[index];
        if (cacheEntry == null) {
            // unknown block, meaning they must be outside the extent at this stage, but might still be inside the shape
            return getBiomeCached(x, z, baseBiome) != null;
        }

        return cacheEntry != OUTSIDE;
    }

    /**
     * Generates the shape.
     *
     * @param editSession The EditSession to use.
     * @param baseBiome The default biome type.
     * @param hollow Specifies whether to generate a hollow shape.
     * @return number of affected blocks.
     */
    public int generate(EditSession editSession, BaseBiome baseBiome, boolean hollow) {
        int affected = 0;

        for (Vector2D position : getExtent()) {
            int x = position.getBlockX();
            int z = position.getBlockZ();

            if (!hollow) {
                final BaseBiome material = getBiome(x, z, baseBiome);
                if (material != OUTSIDE) {
                    editSession.getWorld().setBiome(position, material);
                    ++affected;
                }

                continue;
            }

            final BaseBiome material = getBiomeCached(x, z, baseBiome);
            if (material == null) {
                continue;
            }

            boolean draw = false;
            do {
                if (!isInsideCached(x + 1, z, baseBiome)) {
                    draw = true;
                    break;
                }
                if (!isInsideCached(x - 1, z, baseBiome)) {
                    draw = true;
                    break;
                }
                if (!isInsideCached(x, z + 1, baseBiome)) {
                    draw = true;
                    break;
                }
                if (!isInsideCached(x, z - 1, baseBiome)) {
                    draw = true;
                    break;
                }
            } while (false);

            if (!draw) {
                continue;
            }

            editSession.getWorld().setBiome(position, material);
            ++affected;
        }

        return affected;
    }

    private static final BaseBiome OUTSIDE = new BaseBiome(0) {
        @Override
        public int hashCode() {
            return 0;
        }

        @Override
        public boolean equals(Object o) {
            return this == o;
        }
    };

}
TOP

Related Classes of com.sk89q.worldedit.regions.shape.ArbitraryBiomeShape

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.