com.codelanx.plotted.Range.java Source code

Java tutorial

Introduction

Here is the source code for com.codelanx.plotted.Range.java

Source

/*
 * Copyright (C) 2015 Codelanx, All Rights Reserved
 *
 * This work is licensed under a Creative Commons
 * Attribution-NonCommercial-NoDerivs 3.0 Unported License.
 *
 * This program is protected software: You are free to distrubute your
 * own use of this software under the terms of the Creative Commons BY-NC-ND
 * license as published by Creative Commons in the year 2015 or as published
 * by a later date. You may not provide the source files or provide a means
 * of running the software outside of those licensed to use it.
 *
 * 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.
 *
 * You should have received a copy of the Creative Commons BY-NC-ND license
 * long with this program. If not, see <https://creativecommons.org/licenses/>.
 */
package com.codelanx.plotted;

import com.codelanx.codelanxlib.logging.Debugger;
import com.codelanx.plotted.config.PlotConfig;
import org.apache.commons.lang.Validate;
import org.bukkit.Location;

/**
 * Represents the range at which a plot is located
 *
 * @since 0.0.1
 * @author 1Rogue
 * @version 0.0.1
 */
public class Range implements Comparable<Range>, Cloneable {

    //TODO: refactor for any magnitude (currently made with 100 in mind)
    public static final int MAGNITUDE = PlotConfig.PLOT_SIZE.as(int.class); //Set as an even number for a new map to change island plot size
    private static final int HALFMAG = MAGNITUDE / 2;
    private final int x;
    private final int z;

    public Range(int x, int z) {
        Validate.isTrue(x % Range.MAGNITUDE == 0);
        Validate.isTrue(z % Range.MAGNITUDE == 0);
        this.x = x;
        this.z = z;
    }

    public int getX() {
        return this.x;
    }

    public int getZ() {
        return this.z;
    }

    public boolean contains(int x, int z) {
        return Math.abs(this.x - x) < (Range.HALFMAG) && Math.abs(this.z - z) < (Range.HALFMAG);
    }

    public boolean contains(Location loc) {
        return this.contains(loc.getBlockX(), loc.getBlockZ());
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 59 * hash + this.x;
        hash = 59 * hash + this.z;
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Range other = (Range) obj;
        return this.x == other.x && this.z == other.z;
    }

    @Override
    public int compareTo(Range o) {
        return this.getLocationInSpiral() - o.getLocationInSpiral();
    }

    private int getLocationInSpiral() {
        int mag = Math.max(Math.abs(x), Math.abs(z));
        if (mag == 0) {
            return 0;
        }
        int root = (((mag / Range.MAGNITUDE) - 1) << 1) + 1;
        //next ring start would be the same, without removing 1 from mag/Range.MAG
        int ringInit = root * root;
        Range init = new Range(Range.MAGNITUDE - mag, mag);
        while (!this.equals(init) && Math.abs(init.getZ()) <= mag) {
            init = init.nextIslandLocation();
            ringInit++;
        }
        return ringInit;
    }

    public static Range fromLocation(Location loc) {
        Debugger.print("Rounding %.2f (x) to %d", loc.getX(), Range.round(loc.getX()));
        Debugger.print("Rounding %.2f (z) to %d", loc.getZ(), Range.round(loc.getZ()));
        return new Range(Range.round(loc.getX()), Range.round(loc.getZ()));
    }

    private static int round(double init) { //more of a raise and truncation
        int sign = init < 0 ? -1 : 1;
        init = Math.abs(init);
        init += init % Range.MAGNITUDE >= Range.HALFMAG ? Range.MAGNITUDE : 0;
        return sign * (int) ((long) (init * 1e-2) / 1e-2);
    }

    public Range nextIslandLocation() {
        return Range.nextIslandLocation(this);
    }

    public static Range nextIslandLocation(Range current) {
        return Range.nextIslandLocation(current.x, current.z);
    }

    /**
     * Taken from the old SkySMP plugin for consistency. No logic has been
     * attempted to be improved upon or changed, merely adopted to work with
     * the current plugin (and cleaned up a little). This method should return
     * the next sequential island in the "spiral" for islands
     * 
     * @param x The island x
     * @param z The island z
     * @return A new {@link Range} for the next island
     */
    private static Range nextIslandLocation(int x, int z) {
        //old
        if (x < z) {
            if (-1 * x < z) {
                return new Range(x + Range.MAGNITUDE, z);
            }
            return new Range(x, z + Range.MAGNITUDE);
        }
        if (x > z) {
            if (-1 * x >= z) {
                return new Range(x - Range.MAGNITUDE, z);
            }
            return new Range(x, z - Range.MAGNITUDE);
        }
        return new Range(x, z + ((x <= 0) ? Range.MAGNITUDE : -Range.MAGNITUDE));
    }

    @Override
    public String toString() {
        return "Range[" + this.x + ", " + this.z + "]";
    }

    @Override
    public Range clone() {
        try {
            return (Range) super.clone();
        } catch (CloneNotSupportedException ex) {
            throw new Error("Cannot create clone of Range", ex);
        }
    }

}