Skip to content

Commit ad948f0

Browse files
committed
Rework wall block caching to cache collision shapes as well
1 parent c63a8fa commit ad948f0

File tree

1 file changed

+23
-17
lines changed
  • common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/deduplicate_wall_shapes

1 file changed

+23
-17
lines changed
Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package org.embeddedt.modernfix.common.mixin.perf.deduplicate_wall_shapes;
22

3+
import com.google.common.collect.ImmutableList;
34
import com.google.common.collect.ImmutableMap;
5+
import com.mojang.datafixers.util.Pair;
46
import net.minecraft.world.level.block.Block;
57
import net.minecraft.world.level.block.WallBlock;
68
import net.minecraft.world.level.block.state.BlockState;
@@ -12,43 +14,47 @@
1214
import org.spongepowered.asm.mixin.injection.Inject;
1315
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
1416

15-
import java.util.Arrays;
1617
import java.util.HashMap;
1718
import java.util.Map;
1819

20+
/**
21+
* Most wall blocks use the default set of vanilla properties, and the default sizes for their shapes. This means
22+
* there is no need to reconstruct a separate VoxelShape instance for each wall, we can just repurpose the
23+
* same shape instances. To do this we can cache a mapping between a state (represented only as its prop->value map)
24+
* and the desired shape, and generate the BlockState->VoxelShape map from this for each block.
25+
*/
1926
@Mixin(WallBlock.class)
2027
public abstract class WallBlockMixin extends Block {
21-
private static Map<ImmutableMap<Property<?>, Comparable<?>>, VoxelShape> CACHE_BY_PROPERTIES = new HashMap<>();
22-
private static StateDefinition<Block, BlockState> CACHED_DEFINITION = null;
23-
private static float[] CACHED_FLOATS = null;
28+
private static Map<ImmutableList<Float>, Pair<Map<ImmutableMap<Property<?>, Comparable<?>>, VoxelShape>, StateDefinition<Block, BlockState>>> CACHE_BY_SHAPE_VALS = new HashMap<>();
2429

2530
public WallBlockMixin(Properties properties) {
2631
super(properties);
2732
}
2833

2934
@Inject(method = "makeShapes", at = @At("HEAD"), cancellable = true)
3035
private synchronized void useCachedShapeMap(float f1, float f2, float f3, float f4, float f5, float f6, CallbackInfoReturnable<Map<BlockState, VoxelShape>> cir) {
31-
if(CACHED_DEFINITION != null) {
32-
// check if this state container's properties exactly match the one we used for the cache
33-
if(CACHED_DEFINITION.getProperties().equals(this.stateDefinition.getProperties()) && Arrays.equals(CACHED_FLOATS, new float[] { f1, f2, f3, f4, f5, f6 })) {
34-
ImmutableMap.Builder<BlockState, VoxelShape> builder = ImmutableMap.builder();
35-
for(BlockState state : this.stateDefinition.getPossibleStates()) {
36-
builder.put(state, CACHE_BY_PROPERTIES.get(state.getValues()));
37-
}
38-
cir.setReturnValue(builder.build());
39-
}
36+
ImmutableList<Float> key = ImmutableList.of(f1, f2, f3, f4, f5, f6);
37+
Pair<Map<ImmutableMap<Property<?>, Comparable<?>>, VoxelShape>, StateDefinition<Block, BlockState>> cache = CACHE_BY_SHAPE_VALS.get(key);
38+
// require the properties to be identical
39+
if(cache == null || !cache.getSecond().getProperties().equals(this.stateDefinition.getProperties()))
40+
return;
41+
ImmutableMap.Builder<BlockState, VoxelShape> builder = ImmutableMap.builder();
42+
for(BlockState state : this.stateDefinition.getPossibleStates()) {
43+
builder.put(state, cache.getFirst().get(state.getValues()));
4044
}
45+
cir.setReturnValue(builder.build());
4146
}
4247

4348
@Inject(method = "makeShapes", at = @At("RETURN"))
4449
private synchronized void storeCachedShapesByProperty(float f1, float f2, float f3, float f4, float f5, float f6, CallbackInfoReturnable<Map<BlockState, VoxelShape>> cir) {
45-
if(CACHE_BY_PROPERTIES.size() == 0) {
50+
ImmutableList<Float> key = ImmutableList.of(f1, f2, f3, f4, f5, f6);
51+
if(!CACHE_BY_SHAPE_VALS.containsKey(key)) {
52+
Map<ImmutableMap<Property<?>, Comparable<?>>, VoxelShape> cacheByProperties = new HashMap<>();
4653
Map<BlockState, VoxelShape> shapeMap = cir.getReturnValue();
4754
for(Map.Entry<BlockState, VoxelShape> entry : shapeMap.entrySet()) {
48-
CACHE_BY_PROPERTIES.put(entry.getKey().getValues(), entry.getValue());
55+
cacheByProperties.put(entry.getKey().getValues(), entry.getValue());
4956
}
50-
CACHED_FLOATS = new float[] { f1, f2, f3, f4, f5, f6 };
51-
CACHED_DEFINITION = this.stateDefinition;
57+
CACHE_BY_SHAPE_VALS.put(key, Pair.of(cacheByProperties, this.stateDefinition));
5258
}
5359
}
5460
}

0 commit comments

Comments
 (0)