Skip to content

Commit ef528a4

Browse files
committed
Avoid thread-local map by storing model reference on BlockState object directly
1 parent 792f979 commit ef528a4

File tree

3 files changed

+55
-14
lines changed

3 files changed

+55
-14
lines changed

common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockModelShaperMixin.java

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources;
22

3-
import it.unimi.dsi.fastutil.objects.Reference2ReferenceLinkedOpenHashMap;
43
import net.minecraft.client.renderer.block.BlockModelShaper;
54
import net.minecraft.client.resources.model.BakedModel;
65
import net.minecraft.client.resources.model.ModelManager;
76
import net.minecraft.client.resources.model.ModelResourceLocation;
7+
import net.minecraft.core.registries.BuiltInRegistries;
8+
import net.minecraft.world.level.block.Block;
89
import net.minecraft.world.level.block.state.BlockState;
910
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
11+
import org.embeddedt.modernfix.duck.IModelHoldingBlockState;
1012
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
1113
import org.embeddedt.modernfix.util.DynamicOverridableMap;
1214
import org.spongepowered.asm.mixin.*;
@@ -24,13 +26,18 @@ public class BlockModelShaperMixin {
2426
@Shadow
2527
private Map<BlockState, BakedModel> modelByStateCache;
2628

27-
private ThreadLocal<Reference2ReferenceLinkedOpenHashMap<BlockState, BakedModel>> mfix$modelCache = ThreadLocal.withInitial(Reference2ReferenceLinkedOpenHashMap::new);
28-
2929
@Inject(method = { "<init>", "replaceCache" }, at = @At("RETURN"))
3030
private void replaceModelMap(CallbackInfo ci) {
3131
// replace the backing map for mods which will access it
3232
this.modelByStateCache = new DynamicOverridableMap<>(state -> modelManager.getModel(ModelLocationCache.get(state)));
33-
this.mfix$modelCache = ThreadLocal.withInitial(Reference2ReferenceLinkedOpenHashMap::new);
33+
// Clear the cached models on blockstate objects
34+
for(Block block : BuiltInRegistries.BLOCK) {
35+
for(BlockState state : block.getStateDefinition().getPossibleStates()) {
36+
if(state instanceof IModelHoldingBlockState modelHolder) {
37+
modelHolder.mfix$setModel(null);
38+
}
39+
}
40+
}
3441
}
3542

3643
private BakedModel cacheBlockModel(BlockState state) {
@@ -50,18 +57,18 @@ private BakedModel cacheBlockModel(BlockState state) {
5057
*/
5158
@Overwrite
5259
public BakedModel getBlockModel(BlockState state) {
53-
Reference2ReferenceLinkedOpenHashMap<BlockState, BakedModel> map = this.mfix$modelCache.get();
54-
BakedModel model = map.get(state);
60+
if(state instanceof IModelHoldingBlockState modelHolder) {
61+
BakedModel model = modelHolder.mfix$getModel();
5562

56-
if(model != null) {
57-
return model;
58-
}
63+
if(model != null) {
64+
return model;
65+
}
5966

60-
model = this.cacheBlockModel(state);
61-
map.putAndMoveToFirst(state, model);
62-
if(map.size() > 500) {
63-
map.removeLast();
67+
model = this.cacheBlockModel(state);
68+
modelHolder.mfix$setModel(model);
69+
return model;
70+
} else {
71+
return this.cacheBlockModel(state);
6472
}
65-
return model;
6673
}
6774
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources;
2+
3+
import net.minecraft.client.resources.model.BakedModel;
4+
import net.minecraft.world.level.block.state.BlockBehaviour;
5+
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
6+
import org.embeddedt.modernfix.duck.IModelHoldingBlockState;
7+
import org.spongepowered.asm.mixin.Mixin;
8+
9+
import java.lang.ref.SoftReference;
10+
11+
@Mixin(BlockBehaviour.BlockStateBase.class)
12+
@ClientOnlyMixin
13+
public class BlockStateBaseMixin implements IModelHoldingBlockState {
14+
private volatile SoftReference<BakedModel> mfix$model;
15+
16+
@Override
17+
public BakedModel mfix$getModel() {
18+
var ref = mfix$model;
19+
return ref != null ? ref.get() : null;
20+
}
21+
22+
@Override
23+
public void mfix$setModel(BakedModel model) {
24+
mfix$model = model != null ? new SoftReference<>(model) : null;
25+
}
26+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package org.embeddedt.modernfix.duck;
2+
3+
import net.minecraft.client.resources.model.BakedModel;
4+
5+
public interface IModelHoldingBlockState {
6+
BakedModel mfix$getModel();
7+
void mfix$setModel(BakedModel model);
8+
}

0 commit comments

Comments
 (0)