85 lines
2.5 KiB
Java
85 lines
2.5 KiB
Java
package net.minecraft.util;
|
|
|
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
|
import java.util.Arrays;
|
|
import java.util.Objects;
|
|
import java.util.function.IntFunction;
|
|
import java.util.function.ToIntFunction;
|
|
|
|
public class ByIdMap {
|
|
private static <T> IntFunction<T> createMap(ToIntFunction<T> keyExtractor, T[] values) {
|
|
if (values.length == 0) {
|
|
throw new IllegalArgumentException("Empty value list");
|
|
} else {
|
|
Int2ObjectMap<T> int2ObjectMap = new Int2ObjectOpenHashMap<>();
|
|
|
|
for (T object : values) {
|
|
int i = keyExtractor.applyAsInt(object);
|
|
T object2 = int2ObjectMap.put(i, object);
|
|
if (object2 != null) {
|
|
throw new IllegalArgumentException("Duplicate entry on id " + i + ": current=" + object + ", previous=" + object2);
|
|
}
|
|
}
|
|
|
|
return int2ObjectMap;
|
|
}
|
|
}
|
|
|
|
public static <T> IntFunction<T> sparse(ToIntFunction<T> keyExtractor, T[] values, T fallback) {
|
|
IntFunction<T> intFunction = createMap(keyExtractor, values);
|
|
return i -> Objects.requireNonNullElse(intFunction.apply(i), fallback);
|
|
}
|
|
|
|
private static <T> T[] createSortedArray(ToIntFunction<T> keyExtractor, T[] values) {
|
|
int i = values.length;
|
|
if (i == 0) {
|
|
throw new IllegalArgumentException("Empty value list");
|
|
} else {
|
|
T[] objects = (T[])values.clone();
|
|
Arrays.fill(objects, null);
|
|
|
|
for (T object : values) {
|
|
int j = keyExtractor.applyAsInt(object);
|
|
if (j < 0 || j >= i) {
|
|
throw new IllegalArgumentException("Values are not continous, found index " + j + " for value " + object);
|
|
}
|
|
|
|
T object2 = objects[j];
|
|
if (object2 != null) {
|
|
throw new IllegalArgumentException("Duplicate entry on id " + j + ": current=" + object + ", previous=" + object2);
|
|
}
|
|
|
|
objects[j] = object;
|
|
}
|
|
|
|
for (int k = 0; k < i; k++) {
|
|
if (objects[k] == null) {
|
|
throw new IllegalArgumentException("Missing value at index: " + k);
|
|
}
|
|
}
|
|
|
|
return objects;
|
|
}
|
|
}
|
|
|
|
public static <T> IntFunction<T> continuous(ToIntFunction<T> keyExtractor, T[] values, ByIdMap.OutOfBoundsStrategy outOfBoundsStrategy) {
|
|
T[] objects = (T[])createSortedArray(keyExtractor, values);
|
|
int i = objects.length;
|
|
|
|
return switch (outOfBoundsStrategy) {
|
|
case ZERO -> {
|
|
T object = objects[0];
|
|
yield j -> j >= 0 && j < i ? objects[j] : object;
|
|
}
|
|
case WRAP -> j -> objects[Mth.positiveModulo(j, i)];
|
|
case CLAMP -> j -> objects[Mth.clamp(j, 0, i - 1)];
|
|
};
|
|
}
|
|
|
|
public static enum OutOfBoundsStrategy {
|
|
ZERO,
|
|
WRAP,
|
|
CLAMP;
|
|
}
|
|
}
|