Emulate the vanilla block/item -> model maps for Fabric mods

This commit is contained in:
embeddedt 2023-05-04 17:05:02 -04:00
parent 2b8fc0827c
commit 6c56096556
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
4 changed files with 163 additions and 4 deletions

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

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