/*
* This file is part of NucleusFramework for Bukkit, licensed under the MIT License (MIT).
*
* Copyright (c) JCThePants (www.jcwhatever.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.jcwhatever.nucleus.managed.astar.nodes;
import com.jcwhatever.nucleus.managed.astar.IAStarContext;
import com.jcwhatever.nucleus.managed.astar.score.IAStarScore;
import com.jcwhatever.nucleus.utils.PreCon;
import com.jcwhatever.nucleus.utils.coords.ICoords3Di;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
/**
* Abstract implementation of {@link IAStarNode}.
*/
public abstract class AbstractAStarNode<N extends IAStarNode<N>> implements IAStarNode<N> {
protected IAStarContext<N> _context;
protected N _parent;
protected IAStarScore<N> _score;
protected int _x;
protected int _y;
protected int _z;
/**
* Constructor.
*
* @param x The X coordinate.
* @param y The Y coordinate.
* @param z The Z coordinate.
*/
public AbstractAStarNode(int x, int y, int z) {
_x = x;
_y = y;
_z = z;
}
/**
* Constructor.
*
* @param parent The parent node.
* @param offsetX The X offset from parent.
* @param offsetY The Y offset from parent.
* @param offsetZ The Z offset from parent.
*/
protected AbstractAStarNode(N parent, int offsetX, int offsetY, int offsetZ) {
_parent = parent;
_context = parent.getContext();
_x = parent.getX() + offsetX;
_y = parent.getY() + offsetY;
_z = parent.getZ() + offsetZ;
}
@Override
public IAStarContext<N> getContext() {
return _context;
}
@Override
public <T extends IAStarContext<N>> void setContext(T context) {
_context = context;
}
@Override
public int getX() {
return _x;
}
@Override
public int getY() {
return _y;
}
@Override
public int getZ() {
return _z;
}
@Override
public int getOffsetX() {
return _x - (_parent == null ? _x : _parent.getX());
}
@Override
public int getOffsetY() {
return _y - (_parent == null ? _y : _parent.getY());
}
@Override
public int getOffsetZ() {
return _z - (_parent == null ? _z : _parent.getZ());
}
@Override
public N getParent() {
return _parent;
}
@Override
public void setParent(@Nullable N parent, IAStarScore<N> score) {
PreCon.notNull(score);
_parent = parent;
_score = score;
}
@Override
public Collection<N> getAdjacent() {
return getAdjacent(new ArrayList<N>(9));
}
@Override
public <T extends Collection<N>> T getAdjacent(T output) {
int drop = _context.getSettings().getMaxDropHeight();
for (int x = -1; x <= 1; x++) {
for (int z = -1; z <= 1; z++) {
for (int y = 1; y >= -drop; y--) {
if (x == 0 && z == 0 && y == 0)
continue;
output.add(getRelative(x, y, z));
}
}
}
return output;
}
@Override
public boolean isAdjacent(N node) {
PreCon.notNull(node);
return Math.abs(node.getX() - getX()) <= 1 &&
Math.abs(node.getZ() - getZ()) <= 1;
}
@Nullable
@Override
public IAStarScore<N> getScore() {
if (_score == null && _context != null) {
@SuppressWarnings("unchecked")
N self = (N)this;
_score = _context.getNodeExaminer().getScore(_parent, self);
}
return _score;
}
@Override
public int compareTo(N o) {
PreCon.notNull(o);
IAStarScore<N> score = getScore();
IAStarScore<N> otherScore = o.getScore();
if (score == null)
return otherScore != null ? 1 : 0;
if (otherScore == null)
return -1;
return score.compareTo(otherScore);
}
@Override
public int hashCode() {
return _x ^ _y ^ _z;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof ICoords3Di) {
ICoords3Di other = (ICoords3Di)obj;
return other.getX() == _x &&
other.getY() == _y &&
other.getZ() == _z;
}
return false;
}
}