Merge remote-tracking branch 'origin/1.18' into 1.19.2

This commit is contained in:
embeddedt 2023-05-04 17:06:34 -04:00
commit 0833d4dd56
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
7 changed files with 181 additions and 8 deletions

View File

@ -1,8 +1,6 @@
# ModernFix
A Forge 1.16 mod that uses mixins to make the game slightly more performant (and hopefully less buggy too).
In the words of asiekierka, questionable "performance improvements" that are not in Forge for probably very good reasons.
A performance mod for modern Minecraft that significantly improves launch times, world load times, memory usage, etc.
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.

View File

@ -6,10 +6,13 @@ import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.world.level.block.state.BlockState;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.embeddedt.modernfix.util.DynamicMap;
import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Map;
@Mixin(BlockModelShaper.class)
@ -17,6 +20,15 @@ import org.spongepowered.asm.mixin.Shadow;
public class BlockModelShaperMixin {
@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
* @reason no need to rebuild model cache, and location cache is done elsewhere

View File

@ -1,11 +1,13 @@
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.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.world.item.Item;
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
import org.embeddedt.modernfix.util.DynamicInt2ObjectMap;
import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@ -19,6 +21,8 @@ public abstract class ItemModelShaperMixin {
@Shadow public abstract ModelManager getModelManager();
@Shadow @Final @Mutable private Int2ObjectMap<BakedModel> shapesCache;
private Map<Item, ModelResourceLocation> overrideLocationsVanilla;
public ItemModelShaperMixin() {
@ -30,6 +34,7 @@ public abstract class ItemModelShaperMixin {
@Inject(method = "<init>", at = @At("RETURN"))
private void replaceLocationMap(CallbackInfo ci) {
overrideLocationsVanilla = new HashMap<>();
this.shapesCache = new DynamicInt2ObjectMap<>(index -> getModelManager().getModel(ModelLocationCache.get(Item.byId(index))));
}
@Unique

View File

@ -1,6 +1,7 @@
package org.embeddedt.modernfix.structure;
import com.mojang.datafixers.DataFixer;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import net.minecraft.SharedConstants;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo;
@ -15,6 +16,7 @@ import org.embeddedt.modernfix.util.FileUtil;
import java.io.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Set;
public class CachingStructureManager {
private static ThreadLocal<MessageDigest> digestThreadLocal = ThreadLocal.withInitial(() -> {
@ -45,6 +47,8 @@ public class CachingStructureManager {
return sb.toString();
}
private static final Set<String> laggyStructureMods = new ObjectOpenHashSet<>();
public static CompoundTag readStructureTag(ResourceLocation location, DataFixer datafixer, InputStream stream) throws IOException {
byte[] structureBytes = toBytes(stream);
CompoundTag currentTag = NbtIo.readCompressed(new ByteArrayInputStream(structureBytes));
@ -53,6 +57,11 @@ public class CachingStructureManager {
}
int currentDataVersion = currentTag.getInt("DataVersion");
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 */
MessageDigest hasher = digestThreadLocal.get();
hasher.reset();

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -43,6 +43,7 @@ import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Predicate;
/* high priority so that our injectors are added before other mods' */
@Mixin(value = ModelBakery.class, priority = 600)
@ -165,7 +166,13 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
};
// discard unwrapped models
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());
this.unbakedCache = new LayeredForwardingMap<>(new Map[] { this.unbakedCache, mutableBackingMap });
this.bakedTopLevelModels = new DynamicBakedModelProvider((ModelBakery)(Object)this, bakedCache);