Skip to content

Commit 67814db

Browse files
committed
Mitigate dynres cache thrashing for blocks with more than 10,000 states
The previous implementation kept trying to load the models for all states at once in this scenario, which would cause thrashing as most of the loads would be thrown out. The new implementation limits how many models it will load at a time, but still tries to batch as much as possible
1 parent 8959c2f commit 67814db

File tree

1 file changed

+38
-6
lines changed

1 file changed

+38
-6
lines changed

forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakeryMixin.java

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -305,14 +305,46 @@ public void getOrLoadModelDynamic(ResourceLocation modelLocation, CallbackInfoRe
305305
}
306306
}
307307

308-
private <T extends Comparable<T>, V extends T> BlockState setPropertyGeneric(BlockState state, Property<T> prop, Object o) {
309-
return state.setValue(prop, (V)o);
310-
}
311308
@Redirect(method = "loadModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/StateDefinition;getPossibleStates()Lcom/google/common/collect/ImmutableList;"))
312309
private ImmutableList<BlockState> loadOnlyRelevantBlockState(StateDefinition<Block, BlockState> stateDefinition, ResourceLocation location) {
313-
if(!(location instanceof ModelResourceLocation) || Minecraft.getInstance().getOverlay() != null || Minecraft.getInstance().level == null)
314-
return stateDefinition.getPossibleStates();
315-
return ModelBakeryHelpers.getBlockStatesForMRL(stateDefinition, (ModelResourceLocation)location);
310+
var allStates = stateDefinition.getPossibleStates();
311+
312+
if(!(location instanceof ModelResourceLocation mrl)) {
313+
return allStates;
314+
}
315+
316+
// Load a batch of models at once in certain initialization phases to speed up the loading process.
317+
// This is disabled when in-game as it will cause stutters when blocks are placed.
318+
boolean shouldLoadBatch = (Minecraft.getInstance().getOverlay() != null || Minecraft.getInstance().level == null);
319+
int batchSize = ModelBakeryHelpers.MAX_UNBAKED_MODEL_COUNT - 1000;
320+
321+
// If loading a batch and all the states are smaller than the max batch size, just use them
322+
// This is hoisted above the computation of desiredStates for performance reasons
323+
if (shouldLoadBatch && allStates.size() <= batchSize) {
324+
return allStates;
325+
}
326+
327+
var desiredStates = ModelBakeryHelpers.getBlockStatesForMRL(stateDefinition, mrl);
328+
329+
// If not loading a batch, load only the desired states
330+
if (!shouldLoadBatch) {
331+
return desiredStates;
332+
}
333+
334+
// At this point we want to load a batch if possible, but loading every state is too much. If desiredStates
335+
// is a single state (should almost always be the case), then we choose a sublist starting from it and extending
336+
// batchSize entries (or less if the list ends). If it's multiple states, a single sublist may not include
337+
// everything, so we bail.
338+
if (desiredStates.size() != 1) {
339+
return desiredStates;
340+
}
341+
342+
var desiredState = desiredStates.get(0);
343+
int indexInAllStates = allStates.indexOf(desiredState);
344+
if (indexInAllStates == -1) {
345+
return desiredStates;
346+
}
347+
return allStates.subList(indexInAllStates, Math.min(indexInAllStates + batchSize, allStates.size()));
316348
}
317349

318350
@Override

0 commit comments

Comments
 (0)