Merge remote-tracking branch 'origin/1.19.2' into 1.19.4
This commit is contained in:
commit
95ee0c60ca
|
|
@ -6,7 +6,7 @@ import net.minecraft.client.resources.model.ModelManager;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||||
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
|
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
|
||||||
import org.embeddedt.modernfix.util.DynamicMap;
|
import org.embeddedt.modernfix.util.DynamicOverridableMap;
|
||||||
import org.spongepowered.asm.mixin.*;
|
import org.spongepowered.asm.mixin.*;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
|
@ -26,7 +26,7 @@ public class BlockModelShaperMixin {
|
||||||
@Inject(method = { "<init>", "replaceCache" }, at = @At("RETURN"))
|
@Inject(method = { "<init>", "replaceCache" }, at = @At("RETURN"))
|
||||||
private void replaceModelMap(CallbackInfo ci) {
|
private void replaceModelMap(CallbackInfo ci) {
|
||||||
// replace the backing map for mods which will access it
|
// replace the backing map for mods which will access it
|
||||||
this.modelByStateCache = new DynamicMap<>(state -> modelManager.getModel(ModelLocationCache.get(state)));
|
this.modelByStateCache = new DynamicOverridableMap<>(state -> modelManager.getModel(ModelLocationCache.get(state)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Overwrite
|
@Overwrite
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,13 @@ package org.embeddedt.modernfix.common.mixin.perf.reduce_blockstate_cache_rebuil
|
||||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||||
import org.embeddedt.modernfix.duck.IBlockState;
|
import org.embeddedt.modernfix.duck.IBlockState;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
import org.spongepowered.asm.mixin.Dynamic;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
|
||||||
@Mixin(BlockBehaviour.BlockStateBase.class)
|
@Mixin(BlockBehaviour.BlockStateBase.class)
|
||||||
|
|
@ -23,13 +26,7 @@ public abstract class BlockStateBaseMixin implements IBlockState {
|
||||||
cacheInvalid = true;
|
cacheInvalid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Redirect(method = "*", at = @At(
|
private BlockBehaviour.BlockStateBase.Cache generateCache(BlockBehaviour.BlockStateBase base) {
|
||||||
value = "FIELD",
|
|
||||||
opcode = Opcodes.GETFIELD,
|
|
||||||
target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;cache:Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase$Cache;",
|
|
||||||
ordinal = 0
|
|
||||||
))
|
|
||||||
private BlockBehaviour.BlockStateBase.Cache initCacheIfNeeded(BlockBehaviour.BlockStateBase base) {
|
|
||||||
if(cacheInvalid) {
|
if(cacheInvalid) {
|
||||||
// Ensure that only one block's cache is built at a time
|
// Ensure that only one block's cache is built at a time
|
||||||
synchronized (BlockBehaviour.BlockStateBase.class) {
|
synchronized (BlockBehaviour.BlockStateBase.class) {
|
||||||
|
|
@ -50,4 +47,32 @@ public abstract class BlockStateBaseMixin implements IBlockState {
|
||||||
}
|
}
|
||||||
return this.cache;
|
return this.cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Redirect(method = "*", at = @At(
|
||||||
|
value = "FIELD",
|
||||||
|
opcode = Opcodes.GETFIELD,
|
||||||
|
target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;cache:Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase$Cache;",
|
||||||
|
ordinal = 0
|
||||||
|
))
|
||||||
|
private BlockBehaviour.BlockStateBase.Cache dynamicCacheGen(BlockBehaviour.BlockStateBase base) {
|
||||||
|
return generateCache(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Dynamic
|
||||||
|
@Inject(method = "getPathNodeType", at = @At("HEAD"), require = 0, remap = false)
|
||||||
|
private void generateCacheLithium(CallbackInfoReturnable<?> cir) {
|
||||||
|
generateCache((BlockBehaviour.BlockStateBase)(Object)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Dynamic
|
||||||
|
@Inject(method = "getNeighborPathNodeType", at = @At("HEAD"), require = 0, remap = false)
|
||||||
|
private void generateCacheLithium2(CallbackInfoReturnable<?> cir) {
|
||||||
|
generateCache((BlockBehaviour.BlockStateBase)(Object)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Dynamic
|
||||||
|
@Inject(method = "getAllFlags", at = @At("HEAD"), require = 0, remap = false)
|
||||||
|
private void generateCacheLithium3(CallbackInfoReturnable<?> cir) {
|
||||||
|
generateCache((BlockBehaviour.BlockStateBase)(Object)this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,18 @@ import net.minecraft.world.level.block.state.properties.Property;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class ModelBakeryHelpers {
|
public class ModelBakeryHelpers {
|
||||||
|
/**
|
||||||
|
* The maximum number of baked models kept in memory at once.
|
||||||
|
*/
|
||||||
|
public static final int MAX_BAKED_MODEL_COUNT = 10000;
|
||||||
|
/**
|
||||||
|
* The maximum number of unbaked models kept in memory at once.
|
||||||
|
*/
|
||||||
|
public static final int MAX_UNBAKED_MODEL_COUNT = 10000;
|
||||||
|
/**
|
||||||
|
* The time in seconds after which a model becomes eligible for eviction if not used.
|
||||||
|
*/
|
||||||
|
public static final int MAX_MODEL_LIFETIME_SECS = 300;
|
||||||
|
|
||||||
private static <T extends Comparable<T>, V extends T> BlockState setPropertyGeneric(BlockState state, Property<T> prop, Object o) {
|
private static <T extends Comparable<T>, V extends T> BlockState setPropertyGeneric(BlockState state, Property<T> prop, Object o) {
|
||||||
return state.setValue(prop, (V)o);
|
return state.setValue(prop, (V)o);
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,9 @@ public class EntityRendererMap implements Map<EntityType<?>, EntityRenderer<?>>
|
||||||
if(renderer == null)
|
if(renderer == null)
|
||||||
throw new AssertionError("Returned entity renderer should never be null");
|
throw new AssertionError("Returned entity renderer should never be null");
|
||||||
return renderer;
|
return renderer;
|
||||||
} catch(ExecutionException e) {
|
} catch (IllegalStateException e) {
|
||||||
|
return null; /* emulate value not being present if recursive load occurs */
|
||||||
|
} catch (ExecutionException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package org.embeddedt.modernfix.util;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class DynamicOverridableMap<K, V> extends DynamicMap<K, V> {
|
||||||
|
private final Map<K, V> overrideMap;
|
||||||
|
|
||||||
|
public DynamicOverridableMap(Function<K, V> function) {
|
||||||
|
super(function);
|
||||||
|
overrideMap = new Object2ObjectOpenHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable V put(K k, V v) {
|
||||||
|
if(v == null)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
overrideMap.put(k, v);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V get(Object o) {
|
||||||
|
V val = overrideMap.get(o);
|
||||||
|
if(val != null)
|
||||||
|
return val;
|
||||||
|
return super.get(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putAll(@NotNull Map<? extends K, ? extends V> map) {
|
||||||
|
for(V val : map.values()) {
|
||||||
|
if(val == null)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
overrideMap.putAll(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -77,15 +77,15 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
|
||||||
this.blockColors = val;
|
this.blockColors = val;
|
||||||
this.ignoreModelLoad = true;
|
this.ignoreModelLoad = true;
|
||||||
this.loadedBakedModels = CacheBuilder.newBuilder()
|
this.loadedBakedModels = CacheBuilder.newBuilder()
|
||||||
.expireAfterAccess(3, TimeUnit.MINUTES)
|
.expireAfterAccess(ModelBakeryHelpers.MAX_MODEL_LIFETIME_SECS, TimeUnit.SECONDS)
|
||||||
.maximumSize(1000)
|
.maximumSize(ModelBakeryHelpers.MAX_BAKED_MODEL_COUNT)
|
||||||
.concurrencyLevel(8)
|
.concurrencyLevel(8)
|
||||||
.removalListener(this::onModelRemoved)
|
.removalListener(this::onModelRemoved)
|
||||||
.softValues()
|
.softValues()
|
||||||
.build();
|
.build();
|
||||||
this.loadedModels = CacheBuilder.newBuilder()
|
this.loadedModels = CacheBuilder.newBuilder()
|
||||||
.expireAfterAccess(3, TimeUnit.MINUTES)
|
.expireAfterAccess(ModelBakeryHelpers.MAX_MODEL_LIFETIME_SECS, TimeUnit.SECONDS)
|
||||||
.maximumSize(1000)
|
.maximumSize(ModelBakeryHelpers.MAX_UNBAKED_MODEL_COUNT)
|
||||||
.concurrencyLevel(8)
|
.concurrencyLevel(8)
|
||||||
.removalListener(this::onModelRemoved)
|
.removalListener(this::onModelRemoved)
|
||||||
//.softValues()
|
//.softValues()
|
||||||
|
|
|
||||||
|
|
@ -71,15 +71,15 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
|
||||||
private void replaceTopLevelBakedModels(ModelBakery bakery, BlockColors val) {
|
private void replaceTopLevelBakedModels(ModelBakery bakery, BlockColors val) {
|
||||||
this.blockColors = val;
|
this.blockColors = val;
|
||||||
this.loadedBakedModels = CacheBuilder.newBuilder()
|
this.loadedBakedModels = CacheBuilder.newBuilder()
|
||||||
.expireAfterAccess(3, TimeUnit.MINUTES)
|
.expireAfterAccess(ModelBakeryHelpers.MAX_MODEL_LIFETIME_SECS, TimeUnit.SECONDS)
|
||||||
.maximumSize(1000)
|
.maximumSize(ModelBakeryHelpers.MAX_BAKED_MODEL_COUNT)
|
||||||
.concurrencyLevel(8)
|
.concurrencyLevel(8)
|
||||||
.removalListener(this::onModelRemoved)
|
.removalListener(this::onModelRemoved)
|
||||||
.softValues()
|
.softValues()
|
||||||
.build();
|
.build();
|
||||||
this.loadedModels = CacheBuilder.newBuilder()
|
this.loadedModels = CacheBuilder.newBuilder()
|
||||||
.expireAfterAccess(3, TimeUnit.MINUTES)
|
.expireAfterAccess(ModelBakeryHelpers.MAX_MODEL_LIFETIME_SECS, TimeUnit.SECONDS)
|
||||||
.maximumSize(1000)
|
.maximumSize(ModelBakeryHelpers.MAX_UNBAKED_MODEL_COUNT)
|
||||||
.concurrencyLevel(8)
|
.concurrencyLevel(8)
|
||||||
.removalListener(this::onModelRemoved)
|
.removalListener(this::onModelRemoved)
|
||||||
.softValues()
|
.softValues()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user