1 package org.bukkit.util;
3 import static org.bukkit.util.NumberConversions.*;
5 import org.bukkit.World;
6 import org.bukkit.Location;
7 import org.bukkit.block.Block;
8 import org.bukkit.block.BlockFace;
9 import org.bukkit.entity.LivingEntity;
11 import java.util.Iterator;
12 import java.util.NoSuchElementException;
20 private final World world;
21 private final int maxDistance;
23 private static final int gridSize = 1 << 24;
25 private boolean end =
false;
28 private int currentBlock = 0;
29 private int currentDistance = 0;
30 private int maxDistanceInt;
32 private int secondError;
33 private int thirdError;
35 private int secondStep;
36 private int thirdStep;
55 this.maxDistance = maxDistance;
59 startClone.
setY(startClone.
getY() + yOffset);
63 double mainDirection = 0;
64 double secondDirection = 0;
65 double thirdDirection = 0;
67 double mainPosition = 0;
68 double secondPosition = 0;
69 double thirdPosition = 0;
73 if (getXLength(direction) > mainDirection) {
74 mainFace = getXFace(direction);
75 mainDirection = getXLength(direction);
76 mainPosition = getXPosition(direction, startClone, startBlock);
78 secondFace = getYFace(direction);
79 secondDirection = getYLength(direction);
80 secondPosition = getYPosition(direction, startClone, startBlock);
82 thirdFace = getZFace(direction);
83 thirdDirection = getZLength(direction);
84 thirdPosition = getZPosition(direction, startClone, startBlock);
86 if (getYLength(direction) > mainDirection) {
87 mainFace = getYFace(direction);
88 mainDirection = getYLength(direction);
89 mainPosition = getYPosition(direction, startClone, startBlock);
91 secondFace = getZFace(direction);
92 secondDirection = getZLength(direction);
93 secondPosition = getZPosition(direction, startClone, startBlock);
95 thirdFace = getXFace(direction);
96 thirdDirection = getXLength(direction);
97 thirdPosition = getXPosition(direction, startClone, startBlock);
99 if (getZLength(direction) > mainDirection) {
100 mainFace = getZFace(direction);
101 mainDirection = getZLength(direction);
102 mainPosition = getZPosition(direction, startClone, startBlock);
104 secondFace = getXFace(direction);
105 secondDirection = getXLength(direction);
106 secondPosition = getXPosition(direction, startClone, startBlock);
108 thirdFace = getYFace(direction);
109 thirdDirection = getYLength(direction);
110 thirdPosition = getYPosition(direction, startClone, startBlock);
115 double d = mainPosition / mainDirection;
116 double secondd = secondPosition - secondDirection * d;
117 double thirdd = thirdPosition - thirdDirection * d;
122 secondError = floor(secondd * gridSize);
123 secondStep = round(secondDirection / mainDirection * gridSize);
124 thirdError = floor(thirdd * gridSize);
125 thirdStep = round(thirdDirection / mainDirection * gridSize);
127 if (secondError + secondStep <= 0) {
128 secondError = -secondStep + 1;
131 if (thirdError + thirdStep <= 0) {
132 thirdError = -thirdStep + 1;
139 if (secondError < 0) {
140 secondError += gridSize;
144 if (thirdError < 0) {
145 thirdError += gridSize;
150 secondError -= gridSize;
151 thirdError -= gridSize;
153 blockQueue[0] = lastBlock;
158 boolean startBlockFound =
false;
160 for (
int cnt = currentBlock; cnt >= 0; cnt--) {
161 if (blockEquals(blockQueue[cnt], startBlock)) {
163 startBlockFound =
true;
168 if (!startBlockFound) {
169 throw new IllegalStateException(
"Start block missed in BlockIterator");
173 maxDistanceInt = round(maxDistance / (Math.sqrt(mainDirection * mainDirection + secondDirection * secondDirection + thirdDirection * thirdDirection) / mainDirection));
177 private boolean blockEquals(
Block a,
Block b) {
185 private BlockFace getYFace(Vector direction) {
186 return ((direction.getY() > 0) ? BlockFace.UP : BlockFace.DOWN);
189 private BlockFace getZFace(Vector direction) {
190 return ((direction.getZ() > 0) ? BlockFace.SOUTH : BlockFace.NORTH);
193 private double getXLength(Vector direction) {
194 return Math.abs(direction.getX());
197 private double getYLength(Vector direction) {
198 return Math.abs(direction.getY());
201 private double getZLength(Vector direction) {
202 return Math.abs(direction.getZ());
205 private double getPosition(
double direction,
double position,
int blockPosition) {
206 return direction > 0 ? (position - blockPosition) : (blockPosition + 1 - position);
209 private double getXPosition(Vector direction, Vector position, Block block) {
210 return getPosition(direction.getX(), position.getX(), block.getX());
213 private double getYPosition(Vector direction, Vector position, Block block) {
214 return getPosition(direction.getY(), position.getY(), block.getY());
217 private double getZPosition(Vector direction, Vector position, Block block) {
218 return getPosition(direction.getZ(), position.getZ(), block.getZ());
283 return currentBlock != -1;
294 if (currentBlock <= -1) {
295 throw new NoSuchElementException();
297 return blockQueue[currentBlock--];
301 public void remove() {
302 throw new UnsupportedOperationException(
"[BlockIterator] doesn't support block removal");
305 private void scan() {
306 if (currentBlock >= 0) {
309 if (maxDistance != 0 && currentDistance > maxDistanceInt) {
319 secondError += secondStep;
320 thirdError += thirdStep;
322 if (secondError > 0 && thirdError > 0) {
323 blockQueue[2] = blockQueue[0].
getRelative(mainFace);
324 if (((
long) secondStep) * ((
long) thirdError) < ((
long) thirdStep) * ((
long) secondError)) {
325 blockQueue[1] = blockQueue[2].
getRelative(secondFace);
326 blockQueue[0] = blockQueue[1].
getRelative(thirdFace);
328 blockQueue[1] = blockQueue[2].
getRelative(thirdFace);
329 blockQueue[0] = blockQueue[1].
getRelative(secondFace);
331 thirdError -= gridSize;
332 secondError -= gridSize;
335 }
else if (secondError > 0) {
336 blockQueue[1] = blockQueue[0].
getRelative(mainFace);
337 blockQueue[0] = blockQueue[1].
getRelative(secondFace);
338 secondError -= gridSize;
341 }
else if (thirdError > 0) {
342 blockQueue[1] = blockQueue[0].
getRelative(mainFace);
343 blockQueue[0] = blockQueue[1].
getRelative(thirdFace);
344 thirdError -= gridSize;
348 blockQueue[0] = blockQueue[0].
getRelative(mainFace);