130 lines
4.4 KiB
Java
130 lines
4.4 KiB
Java
package com.hypixel.hytale.server.spawning.suppression;
|
|
|
|
import com.hypixel.hytale.server.spawning.suppression.component.ChunkSuppressionEntry;
|
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
|
import java.util.ArrayDeque;
|
|
import java.util.List;
|
|
import javax.annotation.Nonnull;
|
|
import javax.annotation.Nullable;
|
|
|
|
public class SuppressionSpanHelper {
|
|
private static final ThreadLocal<ArrayDeque<SuppressionSpanHelper.Span>> SPAN_POOL = ThreadLocal.withInitial(ArrayDeque::new);
|
|
private final List<SuppressionSpanHelper.Span> optimisedSuppressionSpans = new ObjectArrayList();
|
|
private int currentSpanIndex = 0;
|
|
|
|
public void optimiseSuppressedSpans(int roleIndex, @Nullable ChunkSuppressionEntry entry) {
|
|
if (entry != null) {
|
|
ArrayDeque<SuppressionSpanHelper.Span> spanPool = SPAN_POOL.get();
|
|
List<ChunkSuppressionEntry.SuppressionSpan> suppressionSpans = entry.getSuppressionSpans();
|
|
SuppressionSpanHelper.Span initialSpan = allocateSpan(spanPool);
|
|
initialSpan.init(0, 0);
|
|
this.optimisedSuppressionSpans.add(initialSpan);
|
|
boolean matchedRole = false;
|
|
|
|
for (ChunkSuppressionEntry.SuppressionSpan suppressionSpan : suppressionSpans) {
|
|
if (suppressionSpan.includesRole(roleIndex)) {
|
|
matchedRole = true;
|
|
int minY = suppressionSpan.getMinY();
|
|
int maxY = suppressionSpan.getMaxY();
|
|
SuppressionSpanHelper.Span latestSpan = this.optimisedSuppressionSpans.getLast();
|
|
if (latestSpan.includes(minY)) {
|
|
if (!latestSpan.includes(maxY)) {
|
|
latestSpan.expandTo(maxY);
|
|
}
|
|
} else {
|
|
SuppressionSpanHelper.Span span = allocateSpan(spanPool);
|
|
span.init(minY, maxY);
|
|
this.optimisedSuppressionSpans.add(span);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!matchedRole) {
|
|
SuppressionSpanHelper.Span span = this.optimisedSuppressionSpans.removeFirst();
|
|
span.reset();
|
|
spanPool.push(span);
|
|
}
|
|
}
|
|
}
|
|
|
|
public int adjustSpawnRangeMin(int min) {
|
|
if (this.optimisedSuppressionSpans.isEmpty()) {
|
|
return min;
|
|
} else {
|
|
int maxSpanIndex = this.optimisedSuppressionSpans.size() - 1;
|
|
|
|
SuppressionSpanHelper.Span currentSpan;
|
|
for (currentSpan = this.optimisedSuppressionSpans.get(this.currentSpanIndex);
|
|
min >= currentSpan.max && this.currentSpanIndex < maxSpanIndex;
|
|
currentSpan = this.optimisedSuppressionSpans.get(this.currentSpanIndex)
|
|
) {
|
|
this.currentSpanIndex++;
|
|
}
|
|
|
|
if (currentSpan.includes(min)) {
|
|
if (this.currentSpanIndex < maxSpanIndex) {
|
|
this.currentSpanIndex++;
|
|
}
|
|
|
|
return currentSpan.max;
|
|
} else {
|
|
return min;
|
|
}
|
|
}
|
|
}
|
|
|
|
public int adjustSpawnRangeMax(int min, int max) {
|
|
if (this.optimisedSuppressionSpans.isEmpty()) {
|
|
return max;
|
|
} else {
|
|
SuppressionSpanHelper.Span currentSpan = this.optimisedSuppressionSpans.get(this.currentSpanIndex);
|
|
if (max < currentSpan.min) {
|
|
return max;
|
|
} else if (currentSpan.includes(max)) {
|
|
return currentSpan.min;
|
|
} else {
|
|
return min < currentSpan.min && max >= currentSpan.max ? currentSpan.min : max;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void reset() {
|
|
ArrayDeque<SuppressionSpanHelper.Span> spanPool = SPAN_POOL.get();
|
|
|
|
for (int i = this.optimisedSuppressionSpans.size() - 1; i >= 0; i--) {
|
|
SuppressionSpanHelper.Span span = this.optimisedSuppressionSpans.remove(i);
|
|
span.reset();
|
|
spanPool.push(span);
|
|
}
|
|
|
|
this.currentSpanIndex = 0;
|
|
}
|
|
|
|
@Nonnull
|
|
private static SuppressionSpanHelper.Span allocateSpan(@Nonnull ArrayDeque<SuppressionSpanHelper.Span> spanPool) {
|
|
return spanPool.isEmpty() ? new SuppressionSpanHelper.Span() : spanPool.pop();
|
|
}
|
|
|
|
private static class Span {
|
|
private int min = -1;
|
|
private int max = -1;
|
|
|
|
public void init(int min, int max) {
|
|
this.min = min;
|
|
this.max = max;
|
|
}
|
|
|
|
public void expandTo(int max) {
|
|
this.max = max;
|
|
}
|
|
|
|
public boolean includes(int value) {
|
|
return value >= this.min && value <= this.max;
|
|
}
|
|
|
|
public void reset() {
|
|
this.min = this.max = -1;
|
|
}
|
|
}
|
|
}
|