98 lines
4.4 KiB
Java
98 lines
4.4 KiB
Java
package com.hypixel.hytale.builtin.hytalegenerator.positionproviders.cached;
|
|
|
|
import com.hypixel.hytale.builtin.hytalegenerator.VectorUtil;
|
|
import com.hypixel.hytale.builtin.hytalegenerator.positionproviders.PositionProvider;
|
|
import com.hypixel.hytale.builtin.hytalegenerator.threadindexer.WorkerIndexer;
|
|
import com.hypixel.hytale.math.util.HashUtil;
|
|
import com.hypixel.hytale.math.vector.Vector3d;
|
|
import com.hypixel.hytale.math.vector.Vector3i;
|
|
import java.util.ArrayList;
|
|
import javax.annotation.Nonnull;
|
|
|
|
public class CachedPositionProvider extends PositionProvider {
|
|
@Nonnull
|
|
private final PositionProvider positionProvider;
|
|
private final int sectionSize;
|
|
private WorkerIndexer.Data<CacheThreadMemory> threadData;
|
|
|
|
public CachedPositionProvider(@Nonnull PositionProvider positionProvider, int sectionSize, int cacheSize, boolean useInternalThreadData, int threadCount) {
|
|
if (sectionSize > 0 && cacheSize >= 0 && threadCount > 0) {
|
|
this.positionProvider = positionProvider;
|
|
this.sectionSize = sectionSize;
|
|
this.threadData = new WorkerIndexer.Data<>(threadCount, () -> new CacheThreadMemory(cacheSize));
|
|
} else {
|
|
throw new IllegalArgumentException();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void positionsIn(@Nonnull PositionProvider.Context context) {
|
|
this.get(context);
|
|
}
|
|
|
|
public void get(@Nonnull PositionProvider.Context context) {
|
|
CacheThreadMemory cachedData = this.threadData.get(context.workerId);
|
|
Vector3i minSection = this.sectionAddress(context.minInclusive);
|
|
Vector3i maxSection = this.sectionAddress(context.maxExclusive);
|
|
Vector3i sectionAddress = minSection.clone();
|
|
|
|
for (sectionAddress.x = minSection.x; sectionAddress.x <= maxSection.x; sectionAddress.x++) {
|
|
for (sectionAddress.z = minSection.z; sectionAddress.z <= maxSection.z; sectionAddress.z++) {
|
|
for (sectionAddress.y = minSection.y; sectionAddress.y <= maxSection.y; sectionAddress.y++) {
|
|
long key = HashUtil.hash(sectionAddress.x, sectionAddress.y, sectionAddress.z);
|
|
Vector3d[] section = cachedData.sections.get(key);
|
|
if (section == null) {
|
|
Vector3d sectionMin = this.sectionMin(sectionAddress);
|
|
Vector3d sectionMax = sectionMin.clone().add(this.sectionSize, this.sectionSize, this.sectionSize);
|
|
ArrayList<Vector3d> generatedPositions = new ArrayList<>();
|
|
PositionProvider.Context childContext = new PositionProvider.Context(sectionMin, sectionMax, generatedPositions::add, null, context.workerId);
|
|
this.positionProvider.positionsIn(childContext);
|
|
section = new Vector3d[generatedPositions.size()];
|
|
generatedPositions.toArray(section);
|
|
cachedData.sections.put(key, section);
|
|
cachedData.expirationList.addFirst(key);
|
|
if (cachedData.expirationList.size() > cachedData.size) {
|
|
long removedKey = cachedData.expirationList.removeLast();
|
|
cachedData.sections.remove(removedKey);
|
|
}
|
|
}
|
|
|
|
for (Vector3d position : section) {
|
|
if (VectorUtil.isInside(position, context.minInclusive, context.maxExclusive)) {
|
|
context.consumer.accept(position.clone());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Nonnull
|
|
private Vector3i sectionAddress(@Nonnull Vector3d pointer) {
|
|
Vector3i address = pointer.toVector3i();
|
|
address.x = this.sectionFloor(address.x) / this.sectionSize;
|
|
address.y = this.sectionFloor(address.y) / this.sectionSize;
|
|
address.z = this.sectionFloor(address.z) / this.sectionSize;
|
|
return address;
|
|
}
|
|
|
|
@Nonnull
|
|
private Vector3d sectionMin(@Nonnull Vector3i sectionAddress) {
|
|
Vector3d min = sectionAddress.toVector3d();
|
|
min.x = min.x * this.sectionSize;
|
|
min.y = min.y * this.sectionSize;
|
|
min.z = min.z * this.sectionSize;
|
|
return min;
|
|
}
|
|
|
|
private int toSectionAddress(double position) {
|
|
int positionAddress = (int)position;
|
|
positionAddress = this.sectionFloor(positionAddress);
|
|
return positionAddress / this.sectionSize;
|
|
}
|
|
|
|
public int sectionFloor(int voxelAddress) {
|
|
return voxelAddress < 0 ? voxelAddress - voxelAddress % this.sectionSize - this.sectionSize : voxelAddress - voxelAddress % this.sectionSize;
|
|
}
|
|
}
|