Make state_definition_construct degrade gracefully if map is used like a hashmap
Related: #452
This commit is contained in:
parent
c0eaf29cb5
commit
49464451dd
|
|
@ -1,5 +1,6 @@
|
|||
package org.embeddedt.modernfix.blockstate;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
|
@ -14,6 +15,7 @@ import java.util.*;
|
|||
*/
|
||||
public class FakeStateMap<S> implements Map<Map<Property<?>, Comparable<?>>, S> {
|
||||
private final Map<Property<?>, Comparable<?>>[] keys;
|
||||
private Map<Map<Property<?>, Comparable<?>>, S> fastLookup;
|
||||
private final Object[] values;
|
||||
private int usedSlots;
|
||||
public FakeStateMap(int numStates) {
|
||||
|
|
@ -34,22 +36,39 @@ public class FakeStateMap<S> implements Map<Map<Property<?>, Comparable<?>>, S>
|
|||
|
||||
@Override
|
||||
public boolean containsKey(Object o) {
|
||||
throw new UnsupportedOperationException();
|
||||
return getFastLookup().containsKey(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object o) {
|
||||
throw new UnsupportedOperationException();
|
||||
return getFastLookup().containsValue(o);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<Map<Property<?>, Comparable<?>>, S> getFastLookup() {
|
||||
if(fastLookup == null) {
|
||||
var map = new Object2ObjectOpenHashMap<Map<Property<?>, Comparable<?>>, S>(usedSlots);
|
||||
Map<Property<?>, Comparable<?>>[] keys = this.keys;
|
||||
Object[] values = this.values;
|
||||
for(int i = 0; i < usedSlots; i++) {
|
||||
map.put(keys[i], (S)values[i]);
|
||||
}
|
||||
fastLookup = map;
|
||||
}
|
||||
return fastLookup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public S get(Object o) {
|
||||
throw new UnsupportedOperationException();
|
||||
return getFastLookup().get(o);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public S put(Map<Property<?>, Comparable<?>> propertyComparableMap, S s) {
|
||||
if(fastLookup != null) {
|
||||
throw new IllegalStateException("Cannot populate map after fast lookup is built");
|
||||
}
|
||||
keys[usedSlots] = propertyComparableMap;
|
||||
values[usedSlots] = s;
|
||||
usedSlots++;
|
||||
|
|
@ -70,7 +89,7 @@ public class FakeStateMap<S> implements Map<Map<Property<?>, Comparable<?>>, S>
|
|||
|
||||
@Override
|
||||
public void clear() {
|
||||
for(int i = 0; i < this.keys.length; i++) {
|
||||
for(int i = 0; i < usedSlots; i++) {
|
||||
this.keys[i] = null;
|
||||
this.values[i] = null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,23 +6,25 @@ import net.minecraft.world.level.block.state.StateHolder;
|
|||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
import org.embeddedt.modernfix.annotation.RequiresMod;
|
||||
import org.embeddedt.modernfix.blockstate.FakeStateMap;
|
||||
import org.embeddedt.modernfix.blockstate.FerriteCorePostProcess;
|
||||
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
// This optimization requires FerriteCore to be worthwhile, otherwise the FakeStateMap degrades to hash internally
|
||||
@Mixin(StateDefinition.class)
|
||||
@RequiresMod("ferritecore")
|
||||
public class StateDefinitionMixin<O, S extends StateHolder<O, S>> {
|
||||
@Shadow @Final private ImmutableSortedMap<String, Property<?>> propertiesByName;
|
||||
|
||||
/**
|
||||
* @author embeddedt
|
||||
* @reason write states into a custom array map for fast iteration by FerriteCore, no need to waste time hashing
|
||||
* and growing
|
||||
*/
|
||||
@ModifyVariable(method = "<init>", at = @At(value = "STORE", ordinal = 0), ordinal = 1, index = 8)
|
||||
private Map<Map<Property<?>, Comparable<?>>, S> useArrayMap(Map<Map<Property<?>, Comparable<?>>, S> in) {
|
||||
int numStates = 1;
|
||||
|
|
@ -31,11 +33,4 @@ public class StateDefinitionMixin<O, S extends StateHolder<O, S>> {
|
|||
}
|
||||
return new FakeStateMap<>(numStates);
|
||||
}
|
||||
|
||||
@Inject(method = "<init>", at = @At("TAIL"))
|
||||
private void postProcess(CallbackInfo ci) {
|
||||
// keep in dev only until upstream FC releases
|
||||
if(ModernFixPlatformHooks.INSTANCE.isDevEnv())
|
||||
FerriteCorePostProcess.postProcess((StateDefinition<O, S>)(Object)this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user