mirror of https://github.com/cabaletta/baritone
127 lines
5.4 KiB
Java
127 lines
5.4 KiB
Java
/*
|
|
* This file is part of Baritone.
|
|
*
|
|
* Baritone is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Baritone 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. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package baritone.builder;
|
|
|
|
import baritone.api.utils.BetterBlockPos;
|
|
import baritone.builder.utils.com.github.btrekkie.connectivity.ConnGraph;
|
|
import baritone.builder.utils.com.github.btrekkie.connectivity.MutatingAugmentation;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.function.Function;
|
|
|
|
public class NavigableSurface {
|
|
|
|
private final CuboidBounds bounds;
|
|
|
|
private final BlockStateCachedData[] blocks; // TODO switch to xzy ordering so columnFrom is faster
|
|
|
|
private final ConnGraph connGraph;
|
|
|
|
private final Function<BetterBlockPos, Object> genVertexAugmentation;
|
|
|
|
private final Column col1 = new Column();
|
|
private final Column col2 = new Column();
|
|
|
|
public NavigableSurface(int x, int y, int z, MutatingAugmentation augmentation, Function<BetterBlockPos, Object> genVertexAugmentation) {
|
|
this.bounds = new CuboidBounds(x, y, z);
|
|
this.blocks = new BlockStateCachedData[bounds.volume()];
|
|
Arrays.fill(blocks, FakeStates.AIR);
|
|
this.genVertexAugmentation = genVertexAugmentation;
|
|
this.connGraph = new ConnGraph(augmentation);
|
|
|
|
if (!genVertexAugmentation.apply(new BetterBlockPos(0, 0, 0)).equals(genVertexAugmentation.apply(new BetterBlockPos(0, 0, 0)))) {
|
|
throw new IllegalStateException("RedBlackNode optimization requires correct impl of .equals on the attachment, to avoid percolating up spurious augmentation non-updates");
|
|
}
|
|
}
|
|
|
|
private void columnFrom(Column column, long pos) {
|
|
column.underneath = getBlockOrAir((pos + Column.DOWN_1) & BetterBlockPos.POST_ADDITION_MASK);
|
|
column.feet = getBlockOrAir(pos);
|
|
column.head = getBlockOrAir((pos + Column.UP_1) & BetterBlockPos.POST_ADDITION_MASK);
|
|
column.above = getBlockOrAir((pos + Column.UP_2) & BetterBlockPos.POST_ADDITION_MASK);
|
|
column.aboveAbove = getBlockOrAir((pos + Column.UP_3) & BetterBlockPos.POST_ADDITION_MASK);
|
|
column.init();
|
|
}
|
|
|
|
protected void setBlock(long pos, BlockStateCachedData data) {
|
|
blocks[bounds.toIndex(pos)] = data;
|
|
for (int dy = -2; dy <= 1; dy++) {
|
|
long couldHaveChanged = BetterBlockPos.offsetBy(pos, 0, dy, 0);
|
|
columnFrom(col1, couldHaveChanged);
|
|
boolean currentlyAllowed = col1.standing();
|
|
if (currentlyAllowed) {
|
|
// TODO skip the next line if it already has an augmentation?
|
|
connGraph.setVertexAugmentation(couldHaveChanged, genVertexAugmentation.apply(BetterBlockPos.fromLong(couldHaveChanged)));
|
|
|
|
for (Face dir : Face.HORIZONTALS) {
|
|
long adj = dir.offset(couldHaveChanged);
|
|
columnFrom(col2, adj);
|
|
Integer connDy = PlayerPhysics.bidirectionalPlayerTravel(col1, col2, getBlockOrAir((adj + Column.DOWN_2) & BetterBlockPos.POST_ADDITION_MASK), getBlockOrAir((adj + Column.DOWN_3) & BetterBlockPos.POST_ADDITION_MASK));
|
|
for (int fakeDy = -2; fakeDy <= 2; fakeDy++) {
|
|
long neighbor = BetterBlockPos.offsetBy(adj, 0, fakeDy, 0);
|
|
if (((Integer) fakeDy).equals(connDy)) {
|
|
connGraph.addEdge(couldHaveChanged, neighbor);
|
|
} else {
|
|
connGraph.removeEdge(couldHaveChanged, neighbor);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
connGraph.removeVertexAugmentation(couldHaveChanged);
|
|
for (Face dir : Face.HORIZONTALS) {
|
|
long adj = dir.offset(couldHaveChanged);
|
|
for (int fakeDy = -2; fakeDy <= 2; fakeDy++) {
|
|
connGraph.removeEdge(couldHaveChanged, BetterBlockPos.offsetBy(adj, 0, fakeDy, 0));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void setBlock(int x, int y, int z, BlockStateCachedData data) {
|
|
setBlock(BetterBlockPos.toLong(x, y, z), data);
|
|
}
|
|
|
|
public CuboidBounds bounds() {
|
|
return bounds;
|
|
}
|
|
|
|
public BlockStateCachedData getBlock(long pos) {
|
|
return blocks[bounds.toIndex(pos)];
|
|
}
|
|
|
|
public BlockStateCachedData getBlockOrAir(long pos) {
|
|
if (!bounds.inRangePos(pos)) {
|
|
return FakeStates.AIR;
|
|
}
|
|
return getBlock(pos);
|
|
}
|
|
|
|
public boolean hasBlock(BetterBlockPos pos) {
|
|
return getBlockOrAir(pos.toLong()).collidesWithPlayer;
|
|
}
|
|
|
|
public boolean connected(BetterBlockPos a, BetterBlockPos b) {
|
|
return connGraph.connected(a.toLong(), b.toLong());
|
|
}
|
|
|
|
public Object getComponentAugmentation(BetterBlockPos pos) { // maybe should be protected? subclass defines it anyway
|
|
return connGraph.getComponentAugmentation(pos.toLong());
|
|
}
|
|
}
|