mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-16 05:02:19 +01:00
Add BlockIterator and LivingEntity#getTargetBlockPosition
This commit is contained in:
parent
f7d1bd7e53
commit
fd73cc1d23
@ -10,6 +10,7 @@ import net.minestom.server.event.entity.EntityDeathEvent;
|
|||||||
import net.minestom.server.event.entity.EntityFireEvent;
|
import net.minestom.server.event.entity.EntityFireEvent;
|
||||||
import net.minestom.server.event.item.PickupItemEvent;
|
import net.minestom.server.event.item.PickupItemEvent;
|
||||||
import net.minestom.server.instance.Chunk;
|
import net.minestom.server.instance.Chunk;
|
||||||
|
import net.minestom.server.instance.block.Block;
|
||||||
import net.minestom.server.inventory.EquipmentHandler;
|
import net.minestom.server.inventory.EquipmentHandler;
|
||||||
import net.minestom.server.item.ItemStack;
|
import net.minestom.server.item.ItemStack;
|
||||||
import net.minestom.server.network.packet.server.play.CollectItemPacket;
|
import net.minestom.server.network.packet.server.play.CollectItemPacket;
|
||||||
@ -19,8 +20,10 @@ import net.minestom.server.network.packet.server.play.SoundEffectPacket;
|
|||||||
import net.minestom.server.scoreboard.Team;
|
import net.minestom.server.scoreboard.Team;
|
||||||
import net.minestom.server.sound.Sound;
|
import net.minestom.server.sound.Sound;
|
||||||
import net.minestom.server.sound.SoundCategory;
|
import net.minestom.server.sound.SoundCategory;
|
||||||
|
import net.minestom.server.utils.BlockPosition;
|
||||||
import net.minestom.server.utils.Position;
|
import net.minestom.server.utils.Position;
|
||||||
import net.minestom.server.utils.binary.BinaryWriter;
|
import net.minestom.server.utils.binary.BinaryWriter;
|
||||||
|
import net.minestom.server.utils.block.BlockIterator;
|
||||||
import net.minestom.server.utils.time.CooldownUtils;
|
import net.minestom.server.utils.time.CooldownUtils;
|
||||||
import net.minestom.server.utils.time.TimeUnit;
|
import net.minestom.server.utils.time.TimeUnit;
|
||||||
import net.minestom.server.utils.time.UpdateOption;
|
import net.minestom.server.utils.time.UpdateOption;
|
||||||
@ -28,6 +31,9 @@ import net.minestom.server.utils.validate.Check;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@ -597,4 +603,36 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
|||||||
public Team getTeam() {
|
public Team getTeam() {
|
||||||
return team;
|
return team;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the line of sight in {@link BlockPosition} of the entity.
|
||||||
|
*
|
||||||
|
* @param maxDistance The max distance to scan
|
||||||
|
* @return A list of {@link BlockPosition} in this entities line of sight
|
||||||
|
*/
|
||||||
|
public List<BlockPosition> getLineOfSight(int maxDistance) {
|
||||||
|
List<BlockPosition> blocks = new ArrayList<>();
|
||||||
|
Iterator<BlockPosition> it = new BlockIterator(this, maxDistance);
|
||||||
|
while(it.hasNext()) {
|
||||||
|
BlockPosition position = it.next();
|
||||||
|
if (Block.fromStateId(getInstance().getBlockStateId(position)) != Block.AIR) blocks.add(position);
|
||||||
|
}
|
||||||
|
return blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the target (not-air) {@link BlockPosition} of the entity.
|
||||||
|
*
|
||||||
|
* @param maxDistance The max distance to scan before returning null
|
||||||
|
* @return The {@link BlockPosition} targeted by this entity, null if non are found
|
||||||
|
*/
|
||||||
|
public BlockPosition getTargetBlockPosition(int maxDistance) {
|
||||||
|
Iterator<BlockPosition> it = new BlockIterator(this, maxDistance);
|
||||||
|
while(it.hasNext()) {
|
||||||
|
BlockPosition position = it.next();
|
||||||
|
if (Block.fromStateId(getInstance().getBlockStateId(position)) != Block.AIR) return position;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package net.minestom.server.instance.block;
|
package net.minestom.server.instance.block;
|
||||||
|
|
||||||
import net.minestom.server.utils.Direction;
|
import net.minestom.server.utils.Direction;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public enum BlockFace {
|
public enum BlockFace {
|
||||||
BOTTOM(Direction.DOWN),
|
BOTTOM(Direction.DOWN),
|
||||||
@ -19,4 +20,23 @@ public enum BlockFace {
|
|||||||
public Direction toDirection() {
|
public Direction toDirection() {
|
||||||
return direction;
|
return direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public BlockFace getOppositeFace() {
|
||||||
|
switch(this) {
|
||||||
|
case BOTTOM:
|
||||||
|
return TOP;
|
||||||
|
case TOP:
|
||||||
|
return BOTTOM;
|
||||||
|
case NORTH:
|
||||||
|
return SOUTH;
|
||||||
|
case SOUTH:
|
||||||
|
return NORTH;
|
||||||
|
case WEST:
|
||||||
|
return EAST;
|
||||||
|
case EAST:
|
||||||
|
return WEST;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.minestom.server.utils;
|
package net.minestom.server.utils;
|
||||||
|
|
||||||
|
import net.minestom.server.instance.block.BlockFace;
|
||||||
import net.minestom.server.utils.clone.PublicCloneable;
|
import net.minestom.server.utils.clone.PublicCloneable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@ -254,6 +255,31 @@ public class BlockPosition implements PublicCloneable<BlockPosition> {
|
|||||||
return new Position(x, y, z);
|
return new Position(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets BlockPosition relative to a {@link BlockFace}
|
||||||
|
*
|
||||||
|
* @param face The blockface touching the relative block
|
||||||
|
* @return The BlockPositon touching the provided blockface
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public BlockPosition getRelative(BlockFace face) {
|
||||||
|
switch(face) {
|
||||||
|
case BOTTOM:
|
||||||
|
return new BlockPosition(getX(), getY() - 1, getZ());
|
||||||
|
case TOP:
|
||||||
|
return new BlockPosition(getX(), getY() + 1, getZ());
|
||||||
|
case NORTH:
|
||||||
|
return new BlockPosition(getX(), getY(), getZ() - 1);
|
||||||
|
case SOUTH:
|
||||||
|
return new BlockPosition(getX(), getY(), getZ() + 1);
|
||||||
|
case WEST:
|
||||||
|
return new BlockPosition(getX() - 1, getY(), getZ());
|
||||||
|
case EAST:
|
||||||
|
return new BlockPosition(getX() + 1, getY(), getZ());
|
||||||
|
}
|
||||||
|
return new BlockPosition(getX(), getY(), getZ()); // should never be called
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
378
src/main/java/net/minestom/server/utils/block/BlockIterator.java
Normal file
378
src/main/java/net/minestom/server/utils/block/BlockIterator.java
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
package net.minestom.server.utils.block;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import net.minestom.server.entity.LivingEntity;
|
||||||
|
import net.minestom.server.instance.block.BlockFace;
|
||||||
|
import net.minestom.server.utils.BlockPosition;
|
||||||
|
import net.minestom.server.utils.Position;
|
||||||
|
import net.minestom.server.utils.Vector;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class performs ray tracing and iterates along blocks on a line
|
||||||
|
*/
|
||||||
|
public class BlockIterator implements Iterator<BlockPosition> {
|
||||||
|
|
||||||
|
private final int maxDistance;
|
||||||
|
|
||||||
|
private static final int gridSize = 1 << 24;
|
||||||
|
|
||||||
|
private boolean end = false;
|
||||||
|
|
||||||
|
private BlockPosition[] blockQueue = new BlockPosition[3];
|
||||||
|
private int currentBlock = 0;
|
||||||
|
private int currentDistance = 0;
|
||||||
|
private int maxDistanceInt;
|
||||||
|
|
||||||
|
private int secondError;
|
||||||
|
private int thirdError;
|
||||||
|
|
||||||
|
private int secondStep;
|
||||||
|
private int thirdStep;
|
||||||
|
|
||||||
|
private BlockFace mainFace;
|
||||||
|
private BlockFace secondFace;
|
||||||
|
private BlockFace thirdFace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the BlockIterator.
|
||||||
|
* <p>
|
||||||
|
* This considers all blocks as 1x1x1 in size.
|
||||||
|
*
|
||||||
|
* @param start A Vector giving the initial position for the trace
|
||||||
|
* @param direction A Vector pointing in the direction for the trace
|
||||||
|
* @param yOffset The trace begins vertically offset from the start vector
|
||||||
|
* by this value
|
||||||
|
* @param maxDistance This is the maximum distance in blocks for the
|
||||||
|
* trace. Setting this value above 140 may lead to problems with
|
||||||
|
* unloaded chunks. A value of 0 indicates no limit
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public BlockIterator(@NotNull Vector start, @NotNull Vector direction, float yOffset, int maxDistance) {
|
||||||
|
this.maxDistance = maxDistance;
|
||||||
|
|
||||||
|
Vector startClone = start.clone();
|
||||||
|
|
||||||
|
startClone.setY(startClone.getY() + yOffset);
|
||||||
|
|
||||||
|
currentDistance = 0;
|
||||||
|
|
||||||
|
double mainDirection = 0;
|
||||||
|
double secondDirection = 0;
|
||||||
|
double thirdDirection = 0;
|
||||||
|
|
||||||
|
double mainPosition = 0;
|
||||||
|
double secondPosition = 0;
|
||||||
|
double thirdPosition = 0;
|
||||||
|
|
||||||
|
BlockPosition startBlock = new BlockPosition(floor(startClone.getX()), floor(startClone.getY()), floor(startClone.getZ()));
|
||||||
|
|
||||||
|
if (getXLength(direction) > mainDirection) {
|
||||||
|
mainFace = getXFace(direction);
|
||||||
|
mainDirection = getXLength(direction);
|
||||||
|
mainPosition = getXPosition(direction, startClone, startBlock);
|
||||||
|
|
||||||
|
secondFace = getYFace(direction);
|
||||||
|
secondDirection = getYLength(direction);
|
||||||
|
secondPosition = getYPosition(direction, startClone, startBlock);
|
||||||
|
|
||||||
|
thirdFace = getZFace(direction);
|
||||||
|
thirdDirection = getZLength(direction);
|
||||||
|
thirdPosition = getZPosition(direction, startClone, startBlock);
|
||||||
|
}
|
||||||
|
if (getYLength(direction) > mainDirection) {
|
||||||
|
mainFace = getYFace(direction);
|
||||||
|
mainDirection = getYLength(direction);
|
||||||
|
mainPosition = getYPosition(direction, startClone, startBlock);
|
||||||
|
|
||||||
|
secondFace = getZFace(direction);
|
||||||
|
secondDirection = getZLength(direction);
|
||||||
|
secondPosition = getZPosition(direction, startClone, startBlock);
|
||||||
|
|
||||||
|
thirdFace = getXFace(direction);
|
||||||
|
thirdDirection = getXLength(direction);
|
||||||
|
thirdPosition = getXPosition(direction, startClone, startBlock);
|
||||||
|
}
|
||||||
|
if (getZLength(direction) > mainDirection) {
|
||||||
|
mainFace = getZFace(direction);
|
||||||
|
mainDirection = getZLength(direction);
|
||||||
|
mainPosition = getZPosition(direction, startClone, startBlock);
|
||||||
|
|
||||||
|
secondFace = getXFace(direction);
|
||||||
|
secondDirection = getXLength(direction);
|
||||||
|
secondPosition = getXPosition(direction, startClone, startBlock);
|
||||||
|
|
||||||
|
thirdFace = getYFace(direction);
|
||||||
|
thirdDirection = getYLength(direction);
|
||||||
|
thirdPosition = getYPosition(direction, startClone, startBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
// trace line backwards to find intercept with plane perpendicular to the main axis
|
||||||
|
|
||||||
|
double d = mainPosition / mainDirection; // how far to hit face behind
|
||||||
|
double secondd = secondPosition - secondDirection * d;
|
||||||
|
double thirdd = thirdPosition - thirdDirection * d;
|
||||||
|
|
||||||
|
// Guarantee that the ray will pass though the start block.
|
||||||
|
// It is possible that it would miss due to rounding
|
||||||
|
// This should only move the ray by 1 grid position
|
||||||
|
secondError = floor(secondd * gridSize);
|
||||||
|
secondStep = round(secondDirection / mainDirection * gridSize);
|
||||||
|
thirdError = floor(thirdd * gridSize);
|
||||||
|
thirdStep = round(thirdDirection / mainDirection * gridSize);
|
||||||
|
|
||||||
|
if (secondError + secondStep <= 0) {
|
||||||
|
secondError = -secondStep + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thirdError + thirdStep <= 0) {
|
||||||
|
thirdError = -thirdStep + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockPosition lastBlock;
|
||||||
|
|
||||||
|
lastBlock = startBlock.getRelative(mainFace.getOppositeFace());
|
||||||
|
|
||||||
|
if (secondError < 0) {
|
||||||
|
secondError += gridSize;
|
||||||
|
lastBlock = lastBlock.getRelative(secondFace.getOppositeFace());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thirdError < 0) {
|
||||||
|
thirdError += gridSize;
|
||||||
|
lastBlock = lastBlock.getRelative(thirdFace.getOppositeFace());
|
||||||
|
}
|
||||||
|
|
||||||
|
// This means that when the variables are positive, it means that the coord=1 boundary has been crossed
|
||||||
|
secondError -= gridSize;
|
||||||
|
thirdError -= gridSize;
|
||||||
|
|
||||||
|
blockQueue[0] = lastBlock;
|
||||||
|
currentBlock = -1;
|
||||||
|
|
||||||
|
scan();
|
||||||
|
|
||||||
|
boolean startBlockFound = false;
|
||||||
|
|
||||||
|
for (int cnt = currentBlock; cnt >= 0; cnt--) {
|
||||||
|
if (blockEquals(blockQueue[cnt], startBlock)) {
|
||||||
|
currentBlock = cnt;
|
||||||
|
startBlockFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!startBlockFound) {
|
||||||
|
throw new IllegalStateException("Start block missed in BlockIterator");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the number of planes passed to give max distance
|
||||||
|
maxDistanceInt = round(maxDistance / (Math.sqrt(mainDirection * mainDirection + secondDirection * secondDirection + thirdDirection * thirdDirection) / mainDirection));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean blockEquals(@NotNull BlockPosition a, @NotNull BlockPosition b) {
|
||||||
|
return a.getX() == b.getX() && a.getY() == b.getY() && a.getZ() == b.getZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockFace getXFace(@NotNull Vector direction) {
|
||||||
|
return ((direction.getX() > 0) ? BlockFace.EAST : BlockFace.WEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockFace getYFace(@NotNull Vector direction) {
|
||||||
|
return ((direction.getY() > 0) ? BlockFace.TOP : BlockFace.BOTTOM);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockFace getZFace(@NotNull Vector direction) {
|
||||||
|
return ((direction.getZ() > 0) ? BlockFace.SOUTH : BlockFace.NORTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getXLength(@NotNull Vector direction) {
|
||||||
|
return Math.abs(direction.getX());
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getYLength(@NotNull Vector direction) {
|
||||||
|
return Math.abs(direction.getY());
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getZLength(@NotNull Vector direction) {
|
||||||
|
return Math.abs(direction.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getPosition(double direction, double position, int blockPosition) {
|
||||||
|
return direction > 0 ? (position - blockPosition) : (blockPosition + 1 - position);
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getXPosition(@NotNull Vector direction, @NotNull Vector position, @NotNull BlockPosition block) {
|
||||||
|
return getPosition(direction.getX(), position.getX(), block.getX());
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getYPosition(@NotNull Vector direction, @NotNull Vector position, @NotNull BlockPosition block) {
|
||||||
|
return getPosition(direction.getY(), position.getY(), block.getY());
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getZPosition(@NotNull Vector direction, @NotNull Vector position, @NotNull BlockPosition block) {
|
||||||
|
return getPosition(direction.getZ(), position.getZ(), block.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the BlockIterator.
|
||||||
|
* <p>
|
||||||
|
* This considers all blocks as 1x1x1 in size.
|
||||||
|
*
|
||||||
|
* @param pos The position for the start of the ray trace
|
||||||
|
* @param yOffset The trace begins vertically offset from the start vector
|
||||||
|
* by this value
|
||||||
|
* @param maxDistance This is the maximum distance in blocks for the
|
||||||
|
* trace. Setting this value above 140 may lead to problems with
|
||||||
|
* unloaded chunks. A value of 0 indicates no limit
|
||||||
|
*/
|
||||||
|
public BlockIterator(@NotNull Position pos, float yOffset, int maxDistance) {
|
||||||
|
this(pos.toVector(), pos.getDirection(), yOffset, maxDistance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the BlockIterator.
|
||||||
|
* <p>
|
||||||
|
* This considers all blocks as 1x1x1 in size.
|
||||||
|
*
|
||||||
|
* @param pos The position for the start of the ray trace
|
||||||
|
* @param yOffset The trace begins vertically offset from the start vector
|
||||||
|
* by this value
|
||||||
|
*/
|
||||||
|
|
||||||
|
public BlockIterator(@NotNull Position pos, float yOffset) {
|
||||||
|
this(pos.toVector(), pos.getDirection(), yOffset, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the BlockIterator.
|
||||||
|
* <p>
|
||||||
|
* This considers all blocks as 1x1x1 in size.
|
||||||
|
*
|
||||||
|
* @param pos The position for the start of the ray trace
|
||||||
|
*/
|
||||||
|
|
||||||
|
public BlockIterator(@NotNull Position pos) {
|
||||||
|
this(pos, 0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the BlockIterator.
|
||||||
|
* <p>
|
||||||
|
* This considers all blocks as 1x1x1 in size.
|
||||||
|
*
|
||||||
|
* @param entity Information from the entity is used to set up the trace
|
||||||
|
* @param maxDistance This is the maximum distance in blocks for the
|
||||||
|
* trace. Setting this value above 140 may lead to problems with
|
||||||
|
* unloaded chunks. A value of 0 indicates no limit
|
||||||
|
*/
|
||||||
|
|
||||||
|
public BlockIterator(@NotNull LivingEntity entity, int maxDistance) {
|
||||||
|
this(entity.getPosition(), entity.getEyeHeight(), maxDistance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the BlockIterator.
|
||||||
|
* <p>
|
||||||
|
* This considers all blocks as 1x1x1 in size.
|
||||||
|
*
|
||||||
|
* @param entity Information from the entity is used to set up the trace
|
||||||
|
*/
|
||||||
|
|
||||||
|
public BlockIterator(@NotNull LivingEntity entity) {
|
||||||
|
this(entity, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the iteration has more elements
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
scan();
|
||||||
|
return currentBlock != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next BlockPosition in the trace
|
||||||
|
*
|
||||||
|
* @return the next BlockPosition in the trace
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public BlockPosition next() throws NoSuchElementException {
|
||||||
|
scan();
|
||||||
|
if (currentBlock <= -1) {
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
} else {
|
||||||
|
return blockQueue[currentBlock--];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
throw new UnsupportedOperationException("[BlockIterator] doesn't support block removal");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scan() {
|
||||||
|
if (currentBlock >= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (maxDistance != 0 && currentDistance > maxDistanceInt) {
|
||||||
|
end = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (end) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentDistance++;
|
||||||
|
|
||||||
|
secondError += secondStep;
|
||||||
|
thirdError += thirdStep;
|
||||||
|
|
||||||
|
if (secondError > 0 && thirdError > 0) {
|
||||||
|
blockQueue[2] = blockQueue[0].getRelative(mainFace);
|
||||||
|
if (((long) secondStep) * ((long) thirdError) < ((long) thirdStep) * ((long) secondError)) {
|
||||||
|
blockQueue[1] = blockQueue[2].getRelative(secondFace);
|
||||||
|
blockQueue[0] = blockQueue[1].getRelative(thirdFace);
|
||||||
|
} else {
|
||||||
|
blockQueue[1] = blockQueue[2].getRelative(thirdFace);
|
||||||
|
blockQueue[0] = blockQueue[1].getRelative(secondFace);
|
||||||
|
}
|
||||||
|
thirdError -= gridSize;
|
||||||
|
secondError -= gridSize;
|
||||||
|
currentBlock = 2;
|
||||||
|
return;
|
||||||
|
} else if (secondError > 0) {
|
||||||
|
blockQueue[1] = blockQueue[0].getRelative(mainFace);
|
||||||
|
blockQueue[0] = blockQueue[1].getRelative(secondFace);
|
||||||
|
secondError -= gridSize;
|
||||||
|
currentBlock = 1;
|
||||||
|
return;
|
||||||
|
} else if (thirdError > 0) {
|
||||||
|
blockQueue[1] = blockQueue[0].getRelative(mainFace);
|
||||||
|
blockQueue[0] = blockQueue[1].getRelative(thirdFace);
|
||||||
|
thirdError -= gridSize;
|
||||||
|
currentBlock = 1;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
blockQueue[0] = blockQueue[0].getRelative(mainFace);
|
||||||
|
currentBlock = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int floor(double num) {
|
||||||
|
final int floor = (int) num;
|
||||||
|
return floor == num ? floor : floor - (int) (Double.doubleToRawLongBits(num) >>> 63);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int round(double num) {
|
||||||
|
return floor(num + 0.5d);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user