Merge remote-tracking branch 'origin/1.18' into 1.19.2
This commit is contained in:
commit
0833d4dd56
|
|
@ -1,8 +1,6 @@
|
||||||
# ModernFix
|
# ModernFix
|
||||||
|
|
||||||
A Forge 1.16 mod that uses mixins to make the game slightly more performant (and hopefully less buggy too).
|
A performance mod for modern Minecraft that significantly improves launch times, world load times, memory usage, etc.
|
||||||
|
|
||||||
In the words of asiekierka, questionable "performance improvements" that are not in Forge for probably very good reasons.
|
|
||||||
|
|
||||||
Some fixes are based on prior work in various Forge PRs (check commit history and/or code comments). The config system
|
Some fixes are based on prior work in various Forge PRs (check commit history and/or code comments). The config system
|
||||||
is directly derived from Sodium and used under the terms of the LGPL-3.0 license.
|
is directly derived from Sodium and used under the terms of the LGPL-3.0 license.
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,13 @@ 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.spongepowered.asm.mixin.Final;
|
import org.embeddedt.modernfix.util.DynamicMap;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.*;
|
||||||
import org.spongepowered.asm.mixin.Overwrite;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
@Mixin(BlockModelShaper.class)
|
@Mixin(BlockModelShaper.class)
|
||||||
|
|
@ -17,6 +20,15 @@ import org.spongepowered.asm.mixin.Shadow;
|
||||||
public class BlockModelShaperMixin {
|
public class BlockModelShaperMixin {
|
||||||
@Shadow @Final private ModelManager modelManager;
|
@Shadow @Final private ModelManager modelManager;
|
||||||
|
|
||||||
|
@Shadow @Final @Mutable
|
||||||
|
private Map<BlockState, BakedModel> modelByStateCache;
|
||||||
|
|
||||||
|
@Inject(method = "<init>", at = @At("RETURN"))
|
||||||
|
private void replaceModelMap(CallbackInfo ci) {
|
||||||
|
// replace the backing map for mods which will access it
|
||||||
|
this.modelByStateCache = new DynamicMap<>(state -> modelManager.getModel(ModelLocationCache.get(state)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author embeddedt
|
* @author embeddedt
|
||||||
* @reason no need to rebuild model cache, and location cache is done elsewhere
|
* @reason no need to rebuild model cache, and location cache is done elsewhere
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources;
|
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
import net.minecraft.client.renderer.ItemModelShaper;
|
import net.minecraft.client.renderer.ItemModelShaper;
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
import net.minecraft.client.resources.model.ModelManager;
|
import net.minecraft.client.resources.model.ModelManager;
|
||||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
|
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
|
||||||
|
import org.embeddedt.modernfix.util.DynamicInt2ObjectMap;
|
||||||
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;
|
||||||
|
|
@ -19,6 +21,8 @@ public abstract class ItemModelShaperMixin {
|
||||||
|
|
||||||
@Shadow public abstract ModelManager getModelManager();
|
@Shadow public abstract ModelManager getModelManager();
|
||||||
|
|
||||||
|
@Shadow @Final @Mutable private Int2ObjectMap<BakedModel> shapesCache;
|
||||||
|
|
||||||
private Map<Item, ModelResourceLocation> overrideLocationsVanilla;
|
private Map<Item, ModelResourceLocation> overrideLocationsVanilla;
|
||||||
|
|
||||||
public ItemModelShaperMixin() {
|
public ItemModelShaperMixin() {
|
||||||
|
|
@ -30,6 +34,7 @@ public abstract class ItemModelShaperMixin {
|
||||||
@Inject(method = "<init>", at = @At("RETURN"))
|
@Inject(method = "<init>", at = @At("RETURN"))
|
||||||
private void replaceLocationMap(CallbackInfo ci) {
|
private void replaceLocationMap(CallbackInfo ci) {
|
||||||
overrideLocationsVanilla = new HashMap<>();
|
overrideLocationsVanilla = new HashMap<>();
|
||||||
|
this.shapesCache = new DynamicInt2ObjectMap<>(index -> getModelManager().getModel(ModelLocationCache.get(Item.byId(index))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package org.embeddedt.modernfix.structure;
|
package org.embeddedt.modernfix.structure;
|
||||||
|
|
||||||
import com.mojang.datafixers.DataFixer;
|
import com.mojang.datafixers.DataFixer;
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||||
import net.minecraft.SharedConstants;
|
import net.minecraft.SharedConstants;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.NbtIo;
|
import net.minecraft.nbt.NbtIo;
|
||||||
|
|
@ -15,6 +16,7 @@ import org.embeddedt.modernfix.util.FileUtil;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class CachingStructureManager {
|
public class CachingStructureManager {
|
||||||
private static ThreadLocal<MessageDigest> digestThreadLocal = ThreadLocal.withInitial(() -> {
|
private static ThreadLocal<MessageDigest> digestThreadLocal = ThreadLocal.withInitial(() -> {
|
||||||
|
|
@ -45,6 +47,8 @@ public class CachingStructureManager {
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Set<String> laggyStructureMods = new ObjectOpenHashSet<>();
|
||||||
|
|
||||||
public static CompoundTag readStructureTag(ResourceLocation location, DataFixer datafixer, InputStream stream) throws IOException {
|
public static CompoundTag readStructureTag(ResourceLocation location, DataFixer datafixer, InputStream stream) throws IOException {
|
||||||
byte[] structureBytes = toBytes(stream);
|
byte[] structureBytes = toBytes(stream);
|
||||||
CompoundTag currentTag = NbtIo.readCompressed(new ByteArrayInputStream(structureBytes));
|
CompoundTag currentTag = NbtIo.readCompressed(new ByteArrayInputStream(structureBytes));
|
||||||
|
|
@ -53,6 +57,11 @@ public class CachingStructureManager {
|
||||||
}
|
}
|
||||||
int currentDataVersion = currentTag.getInt("DataVersion");
|
int currentDataVersion = currentTag.getInt("DataVersion");
|
||||||
if(currentDataVersion < SharedConstants.getCurrentVersion().getWorldVersion()) {
|
if(currentDataVersion < SharedConstants.getCurrentVersion().getWorldVersion()) {
|
||||||
|
synchronized (laggyStructureMods) {
|
||||||
|
if(laggyStructureMods.add(location.getNamespace())) {
|
||||||
|
ModernFix.LOGGER.warn("Mod {} is shipping outdated structure files, which can cause worldgen lag; please report this to them.", location.getNamespace());
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Needs upgrade, try looking up from cache */
|
/* Needs upgrade, try looking up from cache */
|
||||||
MessageDigest hasher = digestThreadLocal.get();
|
MessageDigest hasher = digestThreadLocal.get();
|
||||||
hasher.reset();
|
hasher.reset();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
package org.embeddedt.modernfix.util;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class DynamicInt2ObjectMap<V> extends DynamicMap<Integer, V> implements Int2ObjectMap<V> {
|
||||||
|
public DynamicInt2ObjectMap(Function<Integer, V> function) {
|
||||||
|
super(function);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntSet keySet() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectCollection<V> values() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectSet<Map.Entry<Integer, V>> entrySet() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void defaultReturnValue(V rv) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V defaultReturnValue() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectSet<Int2ObjectMap.Entry<V>> int2ObjectEntrySet() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V getOrDefault(int key, V defaultValue) {
|
||||||
|
V value = get(key);
|
||||||
|
return value == null ? defaultValue : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V get(int key) {
|
||||||
|
return function.apply(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsKey(int key) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
package org.embeddedt.modernfix.util;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class DynamicMap<K, V> implements Map<K, V> {
|
||||||
|
protected final Function<K, V> function;
|
||||||
|
|
||||||
|
public DynamicMap(Function<K, V> function) {
|
||||||
|
this.function = function;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsKey(Object o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsValue(Object o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V get(Object o) {
|
||||||
|
return function.apply((K)o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public V put(K k, V v) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V remove(Object o) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putAll(@NotNull Map<? extends K, ? extends V> map) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Set<K> keySet() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Collection<V> values() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Set<Entry<K, V>> entrySet() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,6 +43,7 @@ import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/* high priority so that our injectors are added before other mods' */
|
/* high priority so that our injectors are added before other mods' */
|
||||||
@Mixin(value = ModelBakery.class, priority = 600)
|
@Mixin(value = ModelBakery.class, priority = 600)
|
||||||
|
|
@ -165,7 +166,13 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
|
||||||
};
|
};
|
||||||
// discard unwrapped models
|
// discard unwrapped models
|
||||||
int oldSize = this.unbakedCache.size();
|
int oldSize = this.unbakedCache.size();
|
||||||
this.unbakedCache.entrySet().removeIf(entry -> entry.getValue() instanceof BlockModel || entry.getValue() instanceof MultiVariant || entry.getValue() instanceof MultiPart);
|
Predicate<Map.Entry<ResourceLocation, UnbakedModel>> isVanillaModel = entry -> entry.getValue() instanceof BlockModel || entry.getValue() instanceof MultiVariant || entry.getValue() instanceof MultiPart;
|
||||||
|
// bake indigo models
|
||||||
|
this.topLevelModels.entrySet().forEach((entry) -> {
|
||||||
|
if(!isVanillaModel.test(entry))
|
||||||
|
this.bake(entry.getKey(), BlockModelRotation.X0_Y0);
|
||||||
|
});
|
||||||
|
this.unbakedCache.entrySet().removeIf(isVanillaModel);
|
||||||
ModernFix.LOGGER.info("{} models evicted, {} custom models loaded permanently", oldSize - this.unbakedCache.size(), this.unbakedCache.size());
|
ModernFix.LOGGER.info("{} models evicted, {} custom models loaded permanently", oldSize - this.unbakedCache.size(), this.unbakedCache.size());
|
||||||
this.unbakedCache = new LayeredForwardingMap<>(new Map[] { this.unbakedCache, mutableBackingMap });
|
this.unbakedCache = new LayeredForwardingMap<>(new Map[] { this.unbakedCache, mutableBackingMap });
|
||||||
this.bakedTopLevelModels = new DynamicBakedModelProvider((ModelBakery)(Object)this, bakedCache);
|
this.bakedTopLevelModels = new DynamicBakedModelProvider((ModelBakery)(Object)this, bakedCache);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user