Skip to content

Commit 69782b8

Browse files
committed
Fix incompatibility with IC2, and VanillaFoodPantry, cache ModelBlockDefinitions
1 parent 3d40b19 commit 69782b8

10 files changed

Lines changed: 108 additions & 55 deletions
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package org.dimdev.utils;
2+
3+
public class IdentityPair<L, R> {
4+
public final L left;
5+
public final R right;
6+
7+
public IdentityPair(L left, R right) {
8+
this.left = left;
9+
this.right = right;
10+
}
11+
12+
@Override
13+
public boolean equals(Object other) {
14+
return other instanceof IdentityPair &&
15+
((IdentityPair) other).left == left &&
16+
((IdentityPair) other).right == right;
17+
}
18+
19+
@Override
20+
public int hashCode() {
21+
return System.identityHashCode(left) + System.identityHashCode(right) * 31;
22+
}
23+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.dimdev.utils;
2+
3+
import java.util.Objects;
4+
5+
public class LeftIdentityPair<L, R> {
6+
public final L left;
7+
public final R right;
8+
9+
public LeftIdentityPair(L left, R right) {
10+
this.left = left;
11+
this.right = right;
12+
}
13+
14+
@Override
15+
public boolean equals(Object other) {
16+
return other instanceof LeftIdentityPair &&
17+
((LeftIdentityPair) other).left == left &&
18+
Objects.equals(((LeftIdentityPair) other).right, right);
19+
}
20+
21+
@Override
22+
public int hashCode() {
23+
return System.identityHashCode(left) + Objects.hashCode(right) * 31;
24+
}
25+
}

src/main/java/org/dimdev/vanillafix/blockstates/NumericalBlockState.java

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@
2121
import net.minecraft.world.World;
2222
import net.minecraftforge.fml.relauncher.Side;
2323
import net.minecraftforge.fml.relauncher.SideOnly;
24-
import org.apache.commons.lang3.tuple.ImmutablePair;
25-
import org.apache.commons.lang3.tuple.Pair;
24+
import org.dimdev.utils.LeftIdentityPair;
2625

2726
import javax.annotation.Nullable;
2827
import java.util.*;
@@ -36,10 +35,10 @@
3635
*/
3736
@SuppressWarnings("deprecation")
3837
public class NumericalBlockState extends BlockStateBase {
39-
private static final Map<Pair<BlockStateContainer, Integer>, NumericalBlockState> blockStates = new HashMap<>(); // TODO: WeakHashMap?
40-
private static final Map<Pair<IProperty<?>, Comparable<?>>, Integer> valueToNumber = new HashMap<>();
41-
private static final Map<Pair<IProperty<?>, Integer>, Comparable<?>> numberToValue = new HashMap<>();
42-
private static final Map<IProperty<?>, Integer> propertyWidths = new HashMap<>();
38+
private static final Map<LeftIdentityPair<BlockStateContainer, Integer>, NumericalBlockState> blockStates = new HashMap<>(); // TODO: WeakHashMap?
39+
private static final Map<LeftIdentityPair<IProperty<?>, Comparable<?>>, Integer> valueToNumber = new HashMap<>();
40+
private static final Map<LeftIdentityPair<IProperty<?>, Integer>, Comparable<?>> numberToValue = new HashMap<>();
41+
private static final Map<IProperty<?>, Integer> propertyWidths = new IdentityHashMap<>();
4342

4443
protected final BlockStateContainer container;
4544
protected final Block block;
@@ -55,7 +54,7 @@ public static NumericalBlockState get(BlockStateContainer container, int data) {
5554
// Getting it from a cache is necessary to make sure == between two NumericalBlockStates
5655
// with the same container and data will work. The cache is shared for all containers
5756
// to avoid the overhead of many small HashMaps.
58-
ImmutablePair<BlockStateContainer, Integer> key = new ImmutablePair<>(container, data);
57+
LeftIdentityPair<BlockStateContainer, Integer> key = new LeftIdentityPair<>(container, data);
5958
NumericalBlockState blockState = blockStates.get(key);
6059

6160
if (blockState == null) {
@@ -72,8 +71,7 @@ public static NumericalBlockState fromPropertyValueMap(BlockStateContainer conta
7271
int data = 0;
7372
for (Map.Entry<IProperty<?>, Comparable<?>> entry : map.entrySet()) {
7473
IProperty<?> property = entry.getKey();
75-
//noinspection SuspiciousMethodCalls
76-
data |= valueToNumber.get(new ImmutablePair<>(property, entry.getValue())) << offsets.get(property);
74+
data |= valueToNumber.get(new LeftIdentityPair<>(property, entry.getValue())) << offsets.get(property);
7775
}
7876

7977
return get(container, data);
@@ -90,8 +88,8 @@ public static <T extends Comparable<T>> void makePropertyInfo(IProperty<T> prope
9088
// Fill the 'number -> value' and 'value -> number' maps
9189
int i = 0;
9290
for (T value : allowedValues) {
93-
numberToValue.put(new ImmutablePair<>(property, i), value);
94-
valueToNumber.put(new ImmutablePair<>(property, value), i);
91+
numberToValue.put(new LeftIdentityPair<>(property, i), value);
92+
valueToNumber.put(new LeftIdentityPair<>(property, value), i);
9593
i++;
9694
}
9795
}
@@ -111,7 +109,7 @@ public <T extends Comparable<T>> T getValue(IProperty<T> property) {
111109

112110
int width = propertyWidths.get(property);
113111
int number = data >>> offset & 0xFFFFFFFF >>> 32 - width;
114-
@SuppressWarnings("SuspiciousMethodCalls") Comparable<?> value = numberToValue.get(new ImmutablePair<>(property, number));
112+
Comparable<?> value = numberToValue.get(new LeftIdentityPair<>(property, number));
115113

116114
return property.getValueClass().cast(value);
117115
}
@@ -124,7 +122,7 @@ public <T extends Comparable<T>, V extends T> IBlockState withProperty(IProperty
124122
throw new IllegalArgumentException("Cannot set property " + property + " as it does not exist in " + container);
125123
}
126124

127-
@SuppressWarnings("SuspiciousMethodCalls") int number = valueToNumber.get(new ImmutablePair<>(property, value));
125+
int number = valueToNumber.get(new LeftIdentityPair<>(property, value));
128126
int width = propertyWidths.get(property);
129127
int mask = (0xFFFFFFFF >>> offset & 0xFFFFFFFF >>> 32 - width) << offset;
130128
int newData = data & ~mask | number << offset;

src/main/java/org/dimdev/vanillafix/blockstates/mixins/MixinBlockStateContainer.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,28 @@ public ImmutableList<IBlockState> getValidStates() {
5757

5858
for (List<Comparable<?>> list : Cartesian.cartesianProduct(getAllowedValues())) {
5959
Map<IProperty<?>, Comparable<?>> propertyValueMap = MapPopulator.createMap(properties.values(), list);
60-
IBlockState state = createState(propertyValueMap, unlistedProperties);
60+
IBlockState state = createState(ImmutableMap.<IProperty<?>, Comparable<?>>builder().putAll(propertyValueMap).build(), unlistedProperties);
6161
states.add(state);
6262
}
6363

64-
validStatesCache = states.build(); // TODO: make validStates a WeakRef/SoftRef?
64+
validStatesCache = states.build();
6565
}
6666

6767
return validStatesCache;
6868
}
6969

70-
protected IBlockState createState(Map<IProperty<?>, Comparable<?>> properties, @Nullable ImmutableMap<IUnlistedProperty<?>, java.util.Optional<?>> unlistedProperties) {
71-
return NumericalBlockState.fromPropertyValueMap((BlockStateContainer) (Object) this, properties);
70+
@Overwrite
71+
protected BlockStateContainer.StateImplementation createState(Block block, ImmutableMap<IProperty<?>, Comparable<?>> properties, @Nullable ImmutableMap<IUnlistedProperty<?>, Optional<?>> unlistedProperties) {
72+
return null;
73+
}
74+
75+
protected IBlockState createState(ImmutableMap<IProperty<?>, Comparable<?>> properties, @Nullable ImmutableMap<IUnlistedProperty<?>, Optional<?>> unlistedProperties) {
76+
BlockStateContainer.StateImplementation state = createState(block, properties, unlistedProperties);
77+
if (state != null) {
78+
return state;
79+
} else {
80+
return NumericalBlockState.fromPropertyValueMap((BlockStateContainer) (Object) this, properties);
81+
}
7282
}
7383

7484
@Overwrite

src/main/java/org/dimdev/vanillafix/blockstates/mixins/MixinExtendedBlockState.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@
33
import com.google.common.collect.ImmutableMap;
44
import net.minecraft.block.Block;
55
import net.minecraft.block.properties.IProperty;
6+
import net.minecraft.block.state.BlockStateContainer;
67
import net.minecraft.block.state.IBlockState;
78
import net.minecraftforge.common.property.ExtendedBlockState;
89
import net.minecraftforge.common.property.IUnlistedProperty;
910
import org.dimdev.vanillafix.blockstates.NumericalExtendedBlockState;
1011
import org.spongepowered.asm.mixin.Mixin;
12+
import org.spongepowered.asm.mixin.Overwrite;
1113

14+
import javax.annotation.Nonnull;
1215
import javax.annotation.Nullable;
13-
import java.util.Map;
1416
import java.util.Optional;
1517

1618
@Mixin(ExtendedBlockState.class)
@@ -20,7 +22,13 @@ public MixinExtendedBlockState(Block block, IProperty<?>[] properties, Immutable
2022
}
2123

2224
@Override
23-
protected IBlockState createState(Map<IProperty<?>, Comparable<?>> properties, @Nullable ImmutableMap<IUnlistedProperty<?>, java.util.Optional<?>> unlistedProperties) {
25+
@Overwrite
26+
protected BlockStateContainer.StateImplementation createState(Block block, ImmutableMap<IProperty<?>, Comparable<?>> properties, @Nullable ImmutableMap<IUnlistedProperty<?>, Optional<?>> unlistedProperties) {
27+
return null;
28+
}
29+
30+
@Override
31+
protected IBlockState createState(ImmutableMap<IProperty<?>, Comparable<?>> properties, @Nullable ImmutableMap<IUnlistedProperty<?>, Optional<?>> unlistedProperties) {
2432
IBlockState normalState = super.createState(properties, unlistedProperties);
2533
if (unlistedProperties == null || unlistedProperties.isEmpty()) {
2634
return normalState;

src/main/java/org/dimdev/vanillafix/blockstates/mixins/MixinPropertyHelper.java

Lines changed: 0 additions & 30 deletions
This file was deleted.

src/main/java/org/dimdev/vanillafix/dynamicresources/model/DynamicBakedModelProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public IBakedModel getObject(ModelResourceLocation location) {
4444
try {
4545
return loadedBakedModels.get(location, () -> Optional.ofNullable(loadBakedModel(location))).orElse(null);
4646
} catch (ExecutionException e) {
47-
throw new RuntimeException(e);
47+
throw new RuntimeException(e.getCause());
4848
}
4949
}
5050

src/main/java/org/dimdev/vanillafix/dynamicresources/model/DynamicModelProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public IModel getObject(ResourceLocation location) {
3737
try {
3838
return loadedModels.get(location, () -> Optional.ofNullable(loadModel(location))).orElse(null);
3939
} catch (ExecutionException e) {
40-
throw new RuntimeException(e);
40+
throw new RuntimeException(e.getCause());
4141
}
4242
}
4343

src/main/java/org/dimdev/vanillafix/dynamicresources/model/VariantLoader.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.dimdev.vanillafix.dynamicresources.model;
22

3+
import com.google.common.cache.Cache;
4+
import com.google.common.cache.CacheBuilder;
35
import com.google.common.collect.Lists;
46
import net.minecraft.block.Block;
57
import net.minecraft.client.Minecraft;
@@ -16,9 +18,18 @@
1618
import java.io.InputStreamReader;
1719
import java.nio.charset.StandardCharsets;
1820
import java.util.List;
21+
import java.util.concurrent.ExecutionException;
22+
import java.util.concurrent.TimeUnit;
1923

2024
public class VariantLoader implements ICustomModelLoader {
2125
public static final VariantLoader INSTANCE = new VariantLoader();
26+
private Cache<ResourceLocation, ModelBlockDefinition> modelBlockDefinitionCache =
27+
CacheBuilder.newBuilder()
28+
.expireAfterAccess(2, TimeUnit.MINUTES)
29+
.maximumSize(100)
30+
.concurrencyLevel(8)
31+
.softValues()
32+
.build();
2233

2334
@Override
2435
public boolean accepts(ResourceLocation modelLocation) {
@@ -28,7 +39,7 @@ public boolean accepts(ResourceLocation modelLocation) {
2839
@Override
2940
public IModel loadModel(ResourceLocation modelLocation) throws Exception {
3041
ModelResourceLocation variant = (ModelResourceLocation) modelLocation;
31-
ModelBlockDefinition definition = loadMultiPartModelBlockDefinition(variant);
42+
ModelBlockDefinition definition = getModelBlockDefinition(variant);
3243

3344
if (definition.hasVariant(variant.getVariant())) {
3445
return new WeightedRandomModel(definition.getVariant(variant.getVariant()));
@@ -44,7 +55,16 @@ public IModel loadModel(ResourceLocation modelLocation) throws Exception {
4455
}
4556
}
4657

47-
private ModelBlockDefinition loadMultiPartModelBlockDefinition(ResourceLocation location) {
58+
private ModelBlockDefinition getModelBlockDefinition(ResourceLocation location) {
59+
ResourceLocation simpleLocation = new ResourceLocation(location.getNamespace(), location.getPath());
60+
try {
61+
return modelBlockDefinitionCache.get(simpleLocation, () -> loadModelBlockDefinition(simpleLocation));
62+
} catch (ExecutionException e) {
63+
throw new RuntimeException(e.getCause());
64+
}
65+
}
66+
67+
private ModelBlockDefinition loadModelBlockDefinition(ResourceLocation location) {
4868
ResourceLocation blockstateLocation = new ResourceLocation(location.getNamespace(), "blockstates/" + location.getPath() + ".json");
4969

5070
List<ModelBlockDefinition> list = Lists.newArrayList();

src/main/resources/mixins.vanillafix.blockstates.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
"compatibilityLevel": "JAVA_8",
99
"mixins": [
1010
"MixinBlockStateContainer",
11-
"MixinExtendedBlockState",
12-
"MixinPropertyHelper"
11+
"MixinExtendedBlockState"
1312
],
1413
"client": [
1514
],

0 commit comments

Comments
 (0)