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;
019
020import net.tridentsdk.world.ChunkLocation;
021
022public final class WorldUtils {
023
024    public static final byte NIBBLE_MASK = (byte) 0x0F;
025
026    private WorldUtils() {
027    }
028
029    /**
030     * Get section index from y height
031     *
032     * @param y the y height specified
033     * @return the section index
034     */
035    public static int section(int y) {
036        return y >> 4;
037    }
038
039    /**
040     * Gets the chunk location from a position X and Y
041     *
042     * @param x the specified x
043     * @param z the specified z
044     * @return the chunk location
045     */
046    public static ChunkLocation chunkLocation(int x, int z) {
047        return ChunkLocation.create(x >> 4, z >> 4);
048    }
049
050    /**
051     * Gets the name of a region file for a given chunklocation
052     *
053     * @param location the location to get the region file for
054     * @return the region file containing the location
055     */
056    public static String regionFile(ChunkLocation location) {
057        return "r." + (location.x() >> 5) + '.' + (location.z() >> 5) + ".mca";
058    }
059
060    /**
061     * Gets a region file name for a given x and y location in the world
062     *
063     * @param x the specified x
064     * @param z the specified z
065     * @return the region file containing the x and y
066     */
067    public static String regionFile(int x, int z) {
068        return "r." + (x >> 9) + '.' + (z >> 9) + ".mca";
069    }
070
071    /**
072     * Gets the index of a block in a section
073     *
074     * @param x the specified x
075     * @param y the y height specified
076     * @param z the specified z
077     * @return the index of the block array containing the coordinates given
078     */
079    public static int blockArrayIndex(int x, int y, int z) {
080        if (x < 0) {
081            x++;
082            x = -x;
083        }
084        if (z < 0) {
085            z++;
086            z = -z;
087        }
088        return (y << 8) + (z << 4) + x;
089    }
090
091    /**
092     * The byte world nibble array byte search
093     *
094     * @param nibbleArray the nibble array to search from
095     * @param index       the nibble index
096     * @return the index of the nibble byte
097     */
098    public static byte fromNibbleArray(byte[] nibbleArray, int index) {
099        boolean off = index % 2 == 1;
100
101        if (off) {
102            return (byte) (nibbleArray[index / 2] >>> 4);
103        } else {
104            return (byte) (nibbleArray[index / 2] & NIBBLE_MASK);
105        }
106    }
107
108    /**
109     * Scales a value, useful for world generation 
110     * @param min the minimum required output
111     * @param max the maximum required output
112     * @param value the value to scale between min and max, should be between -1 and 1
113     * @return a value scaled between min and max by the scaling value, rounded
114     */
115    public static int intScale(int min, int max, double value) {
116        return (int) (((double)(max - min)) * ((value + 1) / 2)) + min;
117    }
118
119    public static int heightIndex(int relX, int relZ) {
120        return (relX * 16) + relZ;
121    }
122}