147 lines
4.1 KiB
Java
147 lines
4.1 KiB
Java
package com.hypixel.hytale.server.spawning.util;
|
|
|
|
import com.hypixel.hytale.math.util.ChunkUtil;
|
|
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
|
|
import java.util.Random;
|
|
import javax.annotation.Nonnull;
|
|
import javax.annotation.Nullable;
|
|
|
|
public class RandomChunkColumnIterator {
|
|
@Nonnull
|
|
private final ChunkColumnMask availablePositions = new ChunkColumnMask();
|
|
@Nullable
|
|
private final ChunkColumnMask initialPositions;
|
|
@Nonnull
|
|
private final Random random = new Random();
|
|
private final long seed;
|
|
private int currentIndex;
|
|
private int lastSavedIteratorPosition;
|
|
|
|
public RandomChunkColumnIterator() {
|
|
this.initialPositions = null;
|
|
this.seed = this.random.nextLong();
|
|
}
|
|
|
|
public RandomChunkColumnIterator(@Nonnull ChunkColumnMask initialPositions) {
|
|
this.initialPositions = initialPositions;
|
|
if (initialPositions.isEmpty()) {
|
|
throw new IllegalArgumentException();
|
|
} else {
|
|
this.seed = this.random.nextLong();
|
|
}
|
|
}
|
|
|
|
public RandomChunkColumnIterator(ChunkColumnMask initialPositions, @Nonnull WorldChunk chunk) {
|
|
this.initialPositions = initialPositions;
|
|
this.seed = (chunk.getX() * 151L + chunk.getZ()) * 131L;
|
|
}
|
|
|
|
public int getCurrentIndex() {
|
|
return this.currentIndex;
|
|
}
|
|
|
|
public int getCurrentX() {
|
|
return ChunkUtil.xFromColumn(this.currentIndex);
|
|
}
|
|
|
|
public int getCurrentZ() {
|
|
return ChunkUtil.zFromColumn(this.currentIndex);
|
|
}
|
|
|
|
@Nullable
|
|
public ChunkColumnMask getInitialPositions() {
|
|
return this.initialPositions;
|
|
}
|
|
|
|
public int nextPosition() {
|
|
if (this.availablePositions.isEmpty()) {
|
|
this.reset();
|
|
}
|
|
|
|
int start = this.random.nextInt(1024);
|
|
int index = this.availablePositions.nextSetBit(start);
|
|
if (index == -1) {
|
|
index = this.availablePositions.previousSetBit(start);
|
|
}
|
|
|
|
return this.nextPosition(index);
|
|
}
|
|
|
|
public int nextPositionAvoidBorders() {
|
|
if (this.availablePositions.isEmpty()) {
|
|
this.reset();
|
|
}
|
|
|
|
int index = this.random.nextInt(1024);
|
|
int start;
|
|
int end;
|
|
if (this.availablePositions.get(index)) {
|
|
start = this.availablePositions.previousClearBit(index) + 1;
|
|
end = this.availablePositions.nextClearBit(index) - 1;
|
|
} else {
|
|
end = this.availablePositions.previousSetBit(index);
|
|
start = this.availablePositions.nextSetBit(index);
|
|
if (end != -1 && (start == -1 || index - end <= start - index)) {
|
|
start = this.availablePositions.previousClearBit(end) + 1;
|
|
} else {
|
|
end = this.availablePositions.nextClearBit(start) - 1;
|
|
}
|
|
}
|
|
|
|
int range = end - start + 1;
|
|
if (range > 3) {
|
|
start += 1 + this.random.nextInt(range - 2);
|
|
} else if (range > 1) {
|
|
start += this.random.nextInt(range);
|
|
}
|
|
|
|
if (!this.availablePositions.get(start)) {
|
|
throw new IllegalArgumentException();
|
|
} else {
|
|
return this.nextPosition(start);
|
|
}
|
|
}
|
|
|
|
public void saveIteratorPosition() {
|
|
this.lastSavedIteratorPosition = this.positionsLeft();
|
|
}
|
|
|
|
public boolean isAtSavedIteratorPosition() {
|
|
return this.positionsLeft() == this.lastSavedIteratorPosition;
|
|
}
|
|
|
|
public int positionsLeft() {
|
|
return this.availablePositions.cardinality();
|
|
}
|
|
|
|
public void markPositionVisited(int index) {
|
|
this.availablePositions.clear(index);
|
|
}
|
|
|
|
public void markPositionVisited() {
|
|
this.markPositionVisited(this.currentIndex);
|
|
}
|
|
|
|
private void reset() {
|
|
this.random.setSeed(this.seed);
|
|
if (this.initialPositions == null) {
|
|
this.availablePositions.set();
|
|
} else {
|
|
if (this.initialPositions.isEmpty()) {
|
|
throw new IllegalArgumentException();
|
|
}
|
|
|
|
this.availablePositions.copyFrom(this.initialPositions);
|
|
}
|
|
}
|
|
|
|
private int nextPosition(int index) {
|
|
if (index == -1) {
|
|
throw new IllegalArgumentException();
|
|
} else {
|
|
this.markPositionVisited(index);
|
|
return this.currentIndex = index;
|
|
}
|
|
}
|
|
}
|