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 */
017package net.tridentsdk.world.gen;
018
019import net.tridentsdk.docs.AccessNoDoc;
020import net.tridentsdk.world.ChunkLocation;
021
022import javax.annotation.concurrent.NotThreadSafe;
023import java.util.Iterator;
024import java.util.NoSuchElementException;
025
026/**
027 * Represents an iterator over chunks within a specified range
028 *
029 * @author The TridentSDK Team
030 * @since 0.3-alpha-DP
031 */
032@NotThreadSafe
033public class ChunkAxisAlignedBoundingBox implements Iterable<ChunkLocation> {
034    final int minX;
035    final int minZ;
036    final int maxX;
037    final int maxZ;
038
039    /**
040     * Creates a new Chunk bounding box
041     *
042     * @param position1 the first chunk corner
043     * @param position2 the second chunk corner
044     */
045    public ChunkAxisAlignedBoundingBox(ChunkLocation position1, ChunkLocation position2) {
046        minX = (position1.x() < position2.x()) ? position1.x() : position2.x();
047        minZ = (position1.z() < position2.z()) ? position1.z() : position2.z();
048
049        maxX = (position1.x() > position2.x()) ? position1.x() : position2.x();
050        maxZ = (position1.z() > position2.z()) ? position1.z() : position2.z();
051    }
052
053    @Override
054    public Iterator<ChunkLocation> iterator() {
055        return new ChunkAABBIterator(this);
056    }
057
058    @AccessNoDoc
059    private class ChunkAABBIterator implements Iterator<ChunkLocation> {
060        private final ChunkAxisAlignedBoundingBox parent;
061
062        private final int xDistance;
063        private final int zDistance;
064        private final int numChunks;
065        private int index = 0;
066
067        private ChunkAABBIterator(ChunkAxisAlignedBoundingBox chunkLocations) {
068            parent = chunkLocations;
069
070            xDistance = parent.maxX - parent.minX + 1;
071            zDistance = parent.maxZ - parent.minZ + 1;
072            numChunks = xDistance * zDistance;
073        }
074
075        @Override
076        public boolean hasNext() {
077            return index < numChunks;
078        }
079
080        @Override
081        public ChunkLocation next() {
082            if (!hasNext()) {
083                throw new NoSuchElementException("No element found past index " + index);
084            }
085            ChunkLocation retVal;
086            if (zDistance == 0 && xDistance == 0) {
087                retVal = ChunkLocation.create(minX, minZ);
088            }
089            else if (zDistance == 0) {
090                retVal = ChunkLocation.create(index % xDistance, minZ);
091            }
092            else if (xDistance == 0) {
093                retVal = ChunkLocation.create(minX, index / zDistance);
094            }
095            else {
096                retVal = ChunkLocation.create(index % xDistance, index / zDistance);
097            }
098            index ++;
099            return retVal;
100        }
101
102        @Override
103        public void remove() {
104            throw new UnsupportedOperationException("Cannot remove items from CAABB");
105        }
106    }
107}