package malte0811.ferritecore; import net.minecraft.state.Property; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; public class FastMap { private final List> keys; private final List> rawKeys; private final List values; public FastMap(Collection> properties, Map, Comparable>, Value> valuesMap) { List> keys = new ArrayList<>(properties.size()); int factorUpTo = 1; for (Property prop : properties) { keys.add(new Key<>(prop, factorUpTo)); factorUpTo *= prop.getAllowedValues().size(); } this.keys = keys; List valuesList = new ArrayList<>(factorUpTo); for (int i = 0; i < factorUpTo; ++i) { valuesList.add(null); } for (Map.Entry, Comparable>, Value> state : valuesMap.entrySet()) { valuesList.set(indexOf(state.getKey()), state.getValue()); } this.values = valuesList; this.rawKeys = new ArrayList<>(properties); } @Nullable public > Value with(int last, Property prop, T value) { final Key keyToChange = indexOf(prop); if (keyToChange == null) { return null; } int newIndex = keyToChange.replaceIn(last, value); if (newIndex < 0) { return null; } return values.get(newIndex); } @Nullable private > Key indexOf(Property prop) { for (Key key : keys) { if (key.getProperty() == prop) { return (Key) key; } } return null; } public int indexOf(Map, Comparable> state) { int id = 0; for (Key k : keys) { id += k.toPartialMapIndex(state.get(k.getProperty())); } return id; } @Nullable public > T getValue(int stateIndex, Property property) { final Key propId = indexOf(property); if (propId == null) { return null; } return propId.getValue(stateIndex); } public Collection> getProperties() { return rawKeys; } private static class Key> { private final Property property; private final List values; private final int mapFactor; private Key(Property property, int mapFactor) { this.property = property; this.values = new ArrayList<>(property.getAllowedValues()); this.mapFactor = mapFactor; } public int toPartialMapIndex(Comparable value) { return mapFactor * getInternalIndex(value); } private int getInternalIndex(Comparable value) { int result = values.indexOf(value); if (result >= 0) { return result; } else { throw new IllegalStateException("Unknown value: "+value+" in "+property); } } public T getValue(int mapIndex) { int index = (mapIndex / mapFactor) % values.size(); return values.get(index); } public int replaceIn(int mapIndex, T newValue) { final int lowerData = mapIndex % mapFactor; final int upperFactor = mapFactor * values.size(); final int upperData = mapIndex - mapIndex % upperFactor; int internalIndex = getInternalIndex(newValue); if (internalIndex < 0) { return -1; } else { return lowerData + mapFactor * internalIndex + upperData; } } public Property getProperty() { return property; } } }