Enable NeoForge project

This commit is contained in:
embeddedt 2024-06-08 21:01:23 -04:00
parent 9d584d13d2
commit 6e9dfaf0c6
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
20 changed files with 49 additions and 895 deletions

View File

@ -1,12 +1,5 @@
package org.embeddedt.modernfix.api.entrypoint;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.*;
import net.minecraft.resources.ResourceLocation;
import java.util.function.Function;
/**
* Implement this interface in a mod class and add it to "modernfix:integration_v1" in your mod metadata file
* to integrate with ModernFix's features.
@ -20,58 +13,4 @@ public interface ModernFixClientIntegration {
*/
default void onDynamicResourcesStatusChange(boolean enabled) {
}
/**
* Called to allow mods to observe the loading of an unbaked model and either make changes to it or wrap it with their
* own instance.
* @param location the ResourceLocation of the model (this may be a ModelResourceLocation)
* @param originalModel the original model
* @param bakery the model bakery - do not touch internal fields as they probably don't behave the way you expect
* with dynamic resources on
* @return the model which should actually be loaded for this resource location
*/
default UnbakedModel onUnbakedModelLoad(ResourceLocation location, UnbakedModel originalModel, ModelBakery bakery) {
return originalModel;
}
/**
* Called to allow mods to observe the use of an unbaked model at bake time and either make changes to it or wrap it with their
* own instance.
* @param location the ResourceLocation of the model (this may be a ModelResourceLocation)
* @param originalModel the original model
* @param bakery the model bakery - do not touch internal fields as they probably don't behave the way you expect
* with dynamic resources on
* @return the model which should actually be loaded for this resource location
*/
default UnbakedModel onUnbakedModelPreBake(ResourceLocation location, UnbakedModel originalModel, ModelBakery bakery) {
return originalModel;
}
/**
* Called to allow mods to observe the loading of a baked model and either make changes to it or wrap it with their
* own instance.
* @param location the ResourceLocation of the model (this may be a ModelResourceLocation)
* @param originalModel the original model
* @param bakery the model bakery - do not touch internal fields as they probably don't behave the way you expect
* with dynamic resources on
* @return the model which should actually be loaded for this resource location
*/
@Deprecated
default BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery) {
return originalModel;
}
/**
* Called to allow mods to observe the loading of a baked model and either make changes to it or wrap it with their
* own instance.
* @param location the ResourceLocation of the model (this may be a ModelResourceLocation)
* @param originalModel the original model
* @param bakery the model bakery - do not touch internal fields as they probably don't behave the way you expect
* with dynamic resources on
* @param textureGetter function to retrieve textures for this model
* @return the model which should actually be loaded for this resource location
*/
default BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery, Function<Material, TextureAtlasSprite> textureGetter) {
return onBakedModelLoad(location, baseModel, originalModel, state, bakery);
}
}

View File

@ -13,6 +13,7 @@ import org.embeddedt.modernfix.searchtree.RecipeBookSearchTree;
import org.embeddedt.modernfix.searchtree.SearchTreeProviderRegistry;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@ -28,6 +29,8 @@ import java.util.concurrent.CompletableFuture;
public abstract class SessionSearchTreesMixin {
@Shadow private CompletableFuture<SearchTree<RecipeCollection>> recipeSearch;
@Shadow private CompletableFuture<SearchTree<ItemStack>> creativeByNameSearch;
@Shadow @Final private static SessionSearchTrees.Key CREATIVE_NAMES;
@Shadow @Final private static SessionSearchTrees.Key CREATIVE_TAGS;
private SearchTreeProviderRegistry.Provider mfix$provider;
@Inject(method = "<init>", at = @At("RETURN"))
@ -63,11 +66,12 @@ public abstract class SessionSearchTreesMixin {
}
}
@ModifyArg(method = "updateCreativeTooltips", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/SessionSearchTrees;register(Lnet/minecraft/client/multiplayer/SessionSearchTrees$Key;Ljava/lang/Runnable;)V"), index = 1)
private Runnable useSearchModItems(Runnable r) {
@ModifyArg(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/SessionSearchTrees;register(Lnet/minecraft/client/multiplayer/SessionSearchTrees$Key;Ljava/lang/Runnable;)V"), index = 1)
private Runnable useOverridenSearchTreeLogic(SessionSearchTrees.Key key, Runnable r) {
if(mfix$provider == null) {
return r;
} else {
}
if(key == CREATIVE_NAMES) {
return () -> {
CompletableFuture<?> old = this.creativeByNameSearch;
this.creativeByNameSearch = CompletableFuture.supplyAsync(() -> {
@ -76,13 +80,7 @@ public abstract class SessionSearchTreesMixin {
old.cancel(true);
};
}
}
@ModifyArg(method = "updateCreativeTags", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/SessionSearchTrees;register(Lnet/minecraft/client/multiplayer/SessionSearchTrees$Key;Ljava/lang/Runnable;)V"), index = 1)
private Runnable useSearchModTags(Runnable r) {
if(mfix$provider == null) {
return r;
} else {
if(key == CREATIVE_TAGS) {
return () -> {
CompletableFuture<?> old = this.creativeByNameSearch;
this.creativeByNameSearch = CompletableFuture.supplyAsync(() -> {
@ -91,5 +89,6 @@ public abstract class SessionSearchTreesMixin {
old.cancel(true);
};
}
return r;
}
}

View File

@ -2,17 +2,13 @@ package org.embeddedt.modernfix.dynamicresources;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.resources.model.*;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.Property;
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
import java.util.*;
import java.util.function.BiFunction;
public class ModelBakeryHelpers {
/**
@ -108,13 +104,4 @@ public class ModelBakeryHelpers {
}
return ImmutableList.copyOf(finalList);
}
public static ModernFixClientIntegration bakedModelWrapper(BiFunction<ResourceLocation, Pair<UnbakedModel, BakedModel>, BakedModel> consumer) {
return new ModernFixClientIntegration() {
@Override
public BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery) {
return consumer.apply(location, Pair.of(baseModel, originalModel));
}
};
}
}

View File

@ -38,4 +38,5 @@ accessible field net/minecraft/client/renderer/block/model/multipart/MultiPart d
accessible field net/minecraft/client/renderer/block/model/ItemOverrides$BakedOverride model Lnet/minecraft/client/resources/model/BakedModel;
mutable field net/minecraft/client/renderer/block/model/ItemOverrides$BakedOverride model Lnet/minecraft/client/resources/model/BakedModel;
accessible field net/minecraft/client/renderer/entity/EnderDragonRenderer$DragonModel entity Lnet/minecraft/world/entity/boss/enderdragon/EnderDragon;
accessible method net/minecraft/world/level/block/state/StateDefinition appendPropertyCodec (Lcom/mojang/serialization/MapCodec;Ljava/util/function/Supplier;Ljava/lang/String;Lnet/minecraft/world/level/block/state/properties/Property;)Lcom/mojang/serialization/MapCodec;
accessible method net/minecraft/world/level/block/state/StateDefinition appendPropertyCodec (Lcom/mojang/serialization/MapCodec;Ljava/util/function/Supplier;Ljava/lang/String;Lnet/minecraft/world/level/block/state/properties/Property;)Lcom/mojang/serialization/MapCodec;
accessible class net/minecraft/client/multiplayer/SessionSearchTrees$Key

View File

@ -5,9 +5,10 @@ junit_version=5.10.0-M1
mixinextras_version=0.3.2
mod_id=modernfix
minecraft_version=1.21-pre3
enabled_platforms=fabric
forge_version=20.6.100-beta
minecraft_version=1.21-pre4
enabled_platforms=fabric,neoforge
forge_version=21.0.0-alpha.1.21-pre4.20240609.000029
neoforge_pr=1076
# parchment_version=2023.07.09
refined_storage_version=4392788
jei_version=16.0.0.28
@ -15,7 +16,7 @@ rei_version=13.0.678
ctm_version=1.20.1-1.1.8+4
kubejs_version=1902.6.0-build.142
rhino_version=1902.2.2-build.268
supported_minecraft_versions=1.21-pre3
supported_minecraft_versions=1.21-pre4
fabric_loader_version=0.15.11
fabric_api_version=0.100.0+1.21

View File

@ -31,6 +31,15 @@ repositories {
}
}
maven { url "https://maven.neoforged.net" }
if(rootProject.hasProperty("neoforge_pr")) {
maven {
url 'https://prmaven.neoforged.net/NeoForge/pr' + rootProject.neoforge_pr
content {
includeModule('net.neoforged', 'neoforge')
includeModule('net.neoforged', 'testframework')
}
}
}
}
dependencies {

View File

@ -32,7 +32,7 @@ public class ModernFixConfig {
public static Set<ResourceLocation> getJeiPluginBlacklist() {
if(jeiPluginBlacklist == null) {
jeiPluginBlacklist = BLACKLIST_ASYNC_JEI_PLUGINS.get().stream().map(ResourceLocation::new).collect(Collectors.toSet());
jeiPluginBlacklist = BLACKLIST_ASYNC_JEI_PLUGINS.get().stream().map(ResourceLocation::parse).collect(Collectors.toSet());
}
return jeiPluginBlacklist;
}

View File

@ -34,10 +34,10 @@ public class ModelBakeEventHelper {
"vampirism",
"elevatorid",
"embers");
private final Map<ResourceLocation, BakedModel> modelRegistry;
private final Set<ResourceLocation> topLevelModelLocations;
private final Map<ModelResourceLocation, BakedModel> modelRegistry;
private final Set<ModelResourceLocation> topLevelModelLocations;
private final MutableGraph<String> dependencyGraph;
public ModelBakeEventHelper(Map<ResourceLocation, BakedModel> modelRegistry) {
public ModelBakeEventHelper(Map<ModelResourceLocation, BakedModel> modelRegistry) {
this.modelRegistry = modelRegistry;
this.topLevelModelLocations = new HashSet<>(modelRegistry.keySet());
// Skip going through ModelLocationCache because most of the accesses will be misses
@ -74,10 +74,10 @@ public class ModelBakeEventHelper {
* @param modId the mod that the event is being fired for
* @return a wrapper around the model registry
*/
private Map<ResourceLocation, BakedModel> createWarningRegistry(String modId) {
return new ForwardingInclDefaultsMap<ResourceLocation, BakedModel>() {
private Map<ModelResourceLocation, BakedModel> createWarningRegistry(String modId) {
return new ForwardingInclDefaultsMap<ModelResourceLocation, BakedModel>() {
@Override
protected Map<ResourceLocation, BakedModel> delegate() {
protected Map<ModelResourceLocation, BakedModel> delegate() {
return modelRegistry;
}
@ -89,13 +89,13 @@ public class ModelBakeEventHelper {
}
@Override
public Set<ResourceLocation> keySet() {
public Set<ModelResourceLocation> keySet() {
logWarning();
return super.keySet();
}
@Override
public Set<Entry<ResourceLocation, BakedModel>> entrySet() {
public Set<Entry<ModelResourceLocation, BakedModel>> entrySet() {
logWarning();
return super.entrySet();
}
@ -107,14 +107,14 @@ public class ModelBakeEventHelper {
}
@Override
public void replaceAll(BiFunction<? super ResourceLocation, ? super BakedModel, ? extends BakedModel> function) {
public void replaceAll(BiFunction<? super ModelResourceLocation, ? super BakedModel, ? extends BakedModel> function) {
logWarning();
super.replaceAll(function);
}
};
}
public Map<ResourceLocation, BakedModel> wrapRegistry(String modId) {
public Map<ModelResourceLocation, BakedModel> wrapRegistry(String modId) {
final Set<String> modIdsToInclude = new HashSet<>();
modIdsToInclude.add(modId);
try {
@ -123,11 +123,11 @@ public class ModelBakeEventHelper {
modIdsToInclude.remove("minecraft");
if(modIdsToInclude.stream().noneMatch(INCOMPATIBLE_MODS::contains))
return createWarningRegistry(modId);
Set<ResourceLocation> ourModelLocations = Sets.filter(this.topLevelModelLocations, loc -> modIdsToInclude.contains(loc.getNamespace()));
Set<ModelResourceLocation> ourModelLocations = Sets.filter(this.topLevelModelLocations, loc -> modIdsToInclude.contains(loc.id().getNamespace()));
BakedModel missingModel = modelRegistry.get(ModelBakery.MISSING_MODEL_LOCATION);
return new ForwardingMap<ResourceLocation, BakedModel>() {
return new ForwardingMap<ModelResourceLocation, BakedModel>() {
@Override
protected Map<ResourceLocation, BakedModel> delegate() {
protected Map<ModelResourceLocation, BakedModel> delegate() {
return modelRegistry;
}
@ -142,7 +142,7 @@ public class ModelBakeEventHelper {
}
@Override
public Set<ResourceLocation> keySet() {
public Set<ModelResourceLocation> keySet() {
return ourModelLocations;
}
@ -152,10 +152,10 @@ public class ModelBakeEventHelper {
}
@Override
public void replaceAll(BiFunction<? super ResourceLocation, ? super BakedModel, ? extends BakedModel> function) {
public void replaceAll(BiFunction<? super ModelResourceLocation, ? super BakedModel, ? extends BakedModel> function) {
ModernFix.LOGGER.warn("Mod '{}' is calling replaceAll on the model registry. Some hacks will be used to keep this fast, but they may not be 100% compatible.", modId);
List<ResourceLocation> locations = new ArrayList<>(keySet());
for(ResourceLocation location : locations) {
List<ModelResourceLocation> locations = new ArrayList<>(keySet());
for(ModelResourceLocation location : locations) {
/*
* Fetching every model is insanely slow. So we call the function with a null object first, since it
* probably isn't expecting that. If we get an exception thrown, or it returns nonnull, then we know

View File

@ -65,7 +65,7 @@ public class ModernFixForge {
event.register(Registries.ITEM, helper -> {
Item.Properties props = new Item.Properties();
for(int i = 0; i < 1000000; i++) {
helper.register(new ResourceLocation("modernfix", "item_" + i), new Item(props));
helper.register(ResourceLocation.fromNamespaceAndPath("modernfix", "item_" + i), new Item(props));
}
});
}

View File

@ -1,56 +0,0 @@
package org.embeddedt.modernfix.neoforge.mixin.bugfix.chunk_deadlock;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.world.level.chunk.LevelChunk;
import net.neoforged.fml.util.ObfuscationReflectionHelper;
import org.embeddedt.modernfix.ModernFix;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import java.lang.reflect.Field;
@Mixin(ChunkMap.class)
public abstract class ChunkMapLoadMixin {
@Shadow @Nullable protected abstract ChunkHolder getVisibleChunkIfPresent(long l);
private static final Field currentlyLoadingField = ObfuscationReflectionHelper.findField(ChunkHolder.class, "currentlyLoading");
private static void setCurrentlyLoading(ChunkHolder holder, LevelChunk value) {
try {
currentlyLoadingField.set(holder, value);
} catch(ReflectiveOperationException e) {
e.printStackTrace();
}
}
/**
* Set currentlyLoading before calling runPostLoad and restore its old value afterwards. We track the old value
* to avoid conflicting with Forge if/when this feature is added.
*/
@WrapOperation(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/LevelChunk;runPostLoad()V"))
private void setCurrentLoadingThenPostLoad(LevelChunk chunk, Operation<Void> operation) {
ChunkHolder holder = this.getVisibleChunkIfPresent(chunk.getPos().toLong());
if(holder != null) {
LevelChunk prevLoading = null;
try {
prevLoading = (LevelChunk)currentlyLoadingField.get(holder);
} catch(ReflectiveOperationException e) {
e.printStackTrace();
}
try {
setCurrentlyLoading(holder, chunk);
operation.call(chunk);
} finally {
setCurrentlyLoading(holder, prevLoading);
}
} else {
ModernFix.LOGGER.warn("Unable to find chunk holder for loading chunk");
operation.call(chunk);
}
}
}

View File

@ -2,7 +2,7 @@ package org.embeddedt.modernfix.neoforge.mixin.perf.dynamic_resources;
import com.google.common.base.Stopwatch;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.neoforged.bus.api.Event;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.ModList;
@ -33,7 +33,7 @@ public class ForgeHooksClientMixin {
ModelBakeEventHelper helper = new ModelBakeEventHelper(bakeEvent.getModels());
Method acceptEv = ObfuscationReflectionHelper.findMethod(ModContainer.class, "acceptEvent", Event.class);
ModList.get().forEachModContainer((id, mc) -> {
Map<ResourceLocation, BakedModel> newRegistry = helper.wrapRegistry(id);
Map<ModelResourceLocation, BakedModel> newRegistry = helper.wrapRegistry(id);
ModelEvent.ModifyBakingResult postedEvent = new ModelEvent.ModifyBakingResult(newRegistry, bakeEvent.getTextureGetter(), bakeEvent.getModelBakery());
Stopwatch timer = Stopwatch.createStarted();
try {

View File

@ -32,7 +32,7 @@ public abstract class ItemModelMesherForgeMixin extends ItemModelShaper {
super(arg);
}
private static final ModelResourceLocation SENTINEL = new ModelResourceLocation(new ResourceLocation("modernfix", "sentinel"), "sentinel");
private static final ModelResourceLocation SENTINEL = new ModelResourceLocation(ResourceLocation.fromNamespaceAndPath("modernfix", "sentinel"), "sentinel");
@Inject(method = "<init>", at = @At("RETURN"))
private void replaceLocationMap(CallbackInfo ci) {

View File

@ -1,34 +0,0 @@
package org.embeddedt.modernfix.neoforge.mixin.perf.dynamic_resources;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.client.renderer.block.model.ItemOverrides;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelBaker;
import net.minecraft.client.resources.model.ModelState;
import net.minecraft.resources.ResourceLocation;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.duck.IExtendedModelBaker;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import java.util.function.Function;
@Mixin(ItemOverrides.class)
@ClientOnlyMixin
public class ItemOverridesForgeMixin {
/**
* @author embeddedt
* @reason servers insist on generating invalid item overrides that have missing models
*/
@WrapOperation(method = "bakeModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelBaker;bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;Ljava/util/function/Function;)Lnet/minecraft/client/resources/model/BakedModel;"), remap = false)
private BakedModel bake(ModelBaker instance, ResourceLocation resourceLocation, ModelState modelState, Function<ResourceLocation, TextureAtlasSprite> spriteGetter, Operation<BakedModel> original) {
boolean prevState = ((IExtendedModelBaker)instance).throwOnMissingModel(false);
try {
return original.call(instance, resourceLocation, modelState, spriteGetter);
} finally {
((IExtendedModelBaker)instance).throwOnMissingModel(prevState);
}
}
}

View File

@ -1,102 +0,0 @@
package org.embeddedt.modernfix.neoforge.mixin.perf.dynamic_resources;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.*;
import net.minecraft.resources.ResourceLocation;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
import org.embeddedt.modernfix.duck.IExtendedModelBaker;
import org.embeddedt.modernfix.duck.IExtendedModelBakery;
import org.embeddedt.modernfix.dynamicresources.ModelMissingException;
import org.embeddedt.modernfix.neoforge.dynresources.IModelBakerImpl;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.function.Function;
@Mixin(value = ModelBakery.ModelBakerImpl.class, priority = 600)
@ClientOnlyMixin
public abstract class ModelBakerImplMixin implements IModelBakerImpl, IExtendedModelBaker {
private static final boolean debugDynamicModelLoading = Boolean.getBoolean("modernfix.debugDynamicModelLoading");
@Shadow @Final private ModelBakery field_40571;
private boolean mfix$ignoreCache = false;
@Shadow @Final private Function<Material, TextureAtlasSprite> modelTextureGetter;
@Override
public void mfix$ignoreCache() {
mfix$ignoreCache = true;
}
private boolean throwIfMissing;
@Override
public boolean throwOnMissingModel(boolean flag) {
boolean old = throwIfMissing;
throwIfMissing = flag;
return old;
}
@Inject(method = "getModel", at = @At("HEAD"), cancellable = true)
private void obtainModel(ResourceLocation arg, CallbackInfoReturnable<UnbakedModel> cir) {
if(debugDynamicModelLoading)
ModernFix.LOGGER.info("Baking {}", arg);
IExtendedModelBakery extendedBakery = (IExtendedModelBakery)this.field_40571;
if(arg instanceof ModelResourceLocation && arg != ModelBakery.MISSING_MODEL_LOCATION) {
// synchronized because we use topLevelModels
synchronized (this.field_40571) {
this.field_40571.loadTopLevel((ModelResourceLocation)arg);
cir.setReturnValue(this.field_40571.topLevelModels.getOrDefault(arg, extendedBakery.mfix$getUnbakedMissingModel()));
// avoid leaks
this.field_40571.topLevelModels.clear();
}
} else
cir.setReturnValue(this.field_40571.getModel(arg));
UnbakedModel toReplace = cir.getReturnValue();
if(true) {
for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) {
try {
toReplace = integration.onUnbakedModelPreBake(arg, toReplace, this.field_40571);
} catch(RuntimeException e) {
ModernFix.LOGGER.error("Exception firing model pre-bake event for {}", arg, e);
}
}
}
cir.setReturnValue(toReplace);
cir.getReturnValue().resolveParents(this.field_40571::getModel);
if(cir.getReturnValue() == extendedBakery.mfix$getUnbakedMissingModel()) {
if(arg != ModelBakery.MISSING_MODEL_LOCATION) {
if(debugDynamicModelLoading)
ModernFix.LOGGER.warn("Model {} not present", arg);
if(throwIfMissing)
throw new ModelMissingException();
}
}
}
@ModifyExpressionValue(method = "bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;Ljava/util/function/Function;)Lnet/minecraft/client/resources/model/BakedModel;", at = @At(value = "INVOKE", target = "Ljava/util/Map;get(Ljava/lang/Object;)Ljava/lang/Object;", ordinal = 0), remap = false)
private Object ignoreCacheIfRequested(Object o) {
return mfix$ignoreCache ? null : o;
}
@WrapOperation(method = "bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;Ljava/util/function/Function;)Lnet/minecraft/client/resources/model/BakedModel;", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/UnbakedModel;bake(Lnet/minecraft/client/resources/model/ModelBaker;Ljava/util/function/Function;Lnet/minecraft/client/resources/model/ModelState;Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/client/resources/model/BakedModel;"))
private BakedModel callBakedModelIntegration(UnbakedModel unbakedModel, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState state, ResourceLocation location, Operation<BakedModel> operation) {
BakedModel model = operation.call(unbakedModel, baker, spriteGetter, state, location);
for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) {
model = integration.onBakedModelLoad(location, unbakedModel, model, state, this.field_40571, spriteGetter);
}
return model;
}
}

View File

@ -1,344 +0,0 @@
package org.embeddedt.modernfix.neoforge.mixin.perf.dynamic_resources;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalNotification;
import com.google.common.collect.ForwardingMap;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.Minecraft;
import net.minecraft.client.color.block.BlockColors;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.*;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.Property;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
import org.embeddedt.modernfix.duck.IExtendedModelBaker;
import org.embeddedt.modernfix.dynamicresources.DynamicBakedModelProvider;
import org.embeddedt.modernfix.duck.IExtendedModelBakery;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.dynamicresources.ModelBakeryHelpers;
import org.objectweb.asm.Opcodes;
import org.slf4j.Logger;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.*;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
/* low priority so that our injectors are added after other mods' */
@Mixin(value = ModelBakery.class, priority = 1100)
@ClientOnlyMixin
public abstract class ModelBakeryMixin implements IExtendedModelBakery {
private static final boolean debugDynamicModelLoading = Boolean.getBoolean("modernfix.debugDynamicModelLoading");
@Shadow @Final @Mutable public Map<ResourceLocation, UnbakedModel> unbakedCache;
@Shadow @Final public static ModelResourceLocation MISSING_MODEL_LOCATION;
@Shadow protected abstract BlockModel loadBlockModel(ResourceLocation location) throws IOException;
@Shadow @Final private Set<ResourceLocation> loadingStack;
@Shadow protected abstract void loadModel(ResourceLocation blockstateLocation) throws Exception;
@Shadow @Final @Mutable
private Map<ResourceLocation, BakedModel> bakedTopLevelModels;
@Shadow @Final @Mutable private Map<ModelBakery.BakedCacheKey, BakedModel> bakedCache;
@Shadow @Final @Mutable private BlockColors blockColors;
@Shadow @Final private static Logger LOGGER;
@Shadow
public abstract void loadTopLevel(ModelResourceLocation modelResourceLocation);
@Shadow public abstract UnbakedModel getModel(ResourceLocation resourceLocation);
private Cache<ModelBakery.BakedCacheKey, BakedModel> loadedBakedModels;
private Cache<ResourceLocation, UnbakedModel> loadedModels;
private HashMap<ResourceLocation, UnbakedModel> smallLoadingCache = new HashMap<>();
private boolean ignoreModelLoad;
// disable fabric recursion
@SuppressWarnings("unused")
private boolean fabric_enableGetOrLoadModelGuard;
@Redirect(method = "<init>", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/client/resources/model/ModelBakery;blockColors:Lnet/minecraft/client/color/block/BlockColors;"))
private void replaceTopLevelBakedModels(ModelBakery bakery, BlockColors val) {
fabric_enableGetOrLoadModelGuard = false;
this.blockColors = val;
this.loadedBakedModels = CacheBuilder.newBuilder()
.expireAfterAccess(ModelBakeryHelpers.MAX_MODEL_LIFETIME_SECS, TimeUnit.SECONDS)
.maximumSize(ModelBakeryHelpers.MAX_BAKED_MODEL_COUNT)
.concurrencyLevel(8)
.removalListener(this::onModelRemoved)
.softValues()
.build();
this.loadedModels = CacheBuilder.newBuilder()
.expireAfterAccess(ModelBakeryHelpers.MAX_MODEL_LIFETIME_SECS, TimeUnit.SECONDS)
.maximumSize(ModelBakeryHelpers.MAX_UNBAKED_MODEL_COUNT)
.concurrencyLevel(8)
.removalListener(this::onModelRemoved)
.softValues()
.build();
this.bakedCache = loadedBakedModels.asMap();
ConcurrentMap<ResourceLocation, UnbakedModel> unbakedCacheBackingMap = loadedModels.asMap();
this.unbakedCache = new ForwardingMap<ResourceLocation, UnbakedModel>() {
@Override
protected Map<ResourceLocation, UnbakedModel> delegate() {
return unbakedCacheBackingMap;
}
@Override
public UnbakedModel put(ResourceLocation key, UnbakedModel value) {
smallLoadingCache.put(key, value);
return super.put(key, value);
}
};
this.bakedTopLevelModels = new DynamicBakedModelProvider((ModelBakery)(Object)this, bakedCache);
}
@ModifyArg(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiling/ProfilerFiller;popPush(Ljava/lang/String;)V", ordinal = 0), index = 0)
private String ignoreFutureModelLoads(String name) {
this.ignoreModelLoad = true;
return name;
}
private <K, V> void onModelRemoved(RemovalNotification<K, V> notification) {
if(!debugDynamicModelLoading)
return;
Object k = notification.getKey();
if(k == null)
return;
ResourceLocation rl;
boolean baked = false;
if(k instanceof ResourceLocation) {
rl = (ResourceLocation)k;
} else {
rl = ((ModelBakery.BakedCacheKey)k).id();
baked = true;
}
/* can fire when a model is replaced */
if(!baked && this.loadedModels.getIfPresent(rl) != null)
return;
ModernFix.LOGGER.warn("Evicted {} model {}", baked ? "baked" : "unbaked", rl);
}
private UnbakedModel missingModel;
private Set<ResourceLocation> blockStateFiles;
private Set<ResourceLocation> modelFiles;
@ModifyArg(method = "<init>", at = @At(value = "INVOKE", target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", ordinal = 0), index = 1)
private Object captureMissingModel(Object model) {
this.missingModel = (UnbakedModel)model;
this.blockStateFiles = new HashSet<>();
this.modelFiles = new HashSet<>();
return this.missingModel;
}
/**
* @author embeddedt
* @reason don't actually load most models
*/
@Redirect(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelBakery;loadTopLevel(Lnet/minecraft/client/resources/model/ModelResourceLocation;)V"))
private void addTopLevelFile(ModelBakery bakery, ModelResourceLocation location) {
if(location == MISSING_MODEL_LOCATION || !this.ignoreModelLoad) {
loadTopLevel(location);
}
}
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Ljava/util/Map;forEach(Ljava/util/function/BiConsumer;)V", ordinal = 0))
private void fetchStaticDefinitions(Map<ResourceLocation, StateDefinition<Block, BlockState>> map, BiConsumer<ResourceLocation, StateDefinition<Block, BlockState>> func) {
/* no-op */
}
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/StateDefinition;getPossibleStates()Lcom/google/common/collect/ImmutableList;", ordinal = 0))
private ImmutableList<BlockState> fetchBlocks(StateDefinition<Block, BlockState> def) {
/* no-op */
return ImmutableList.of();
}
/**
* Make a copy of the top-level model list to avoid CME if more models get loaded here.
*/
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Ljava/util/Map;values()Ljava/util/Collection;", ordinal = 0))
private Collection<?> copyTopLevelModelList(Map<?, ?> map) {
return new ArrayList<>(map.values());
}
private BiFunction<ResourceLocation, Material, TextureAtlasSprite> textureGetter;
@Inject(method = "bakeModels", at = @At("HEAD"))
private void captureGetter(BiFunction<ResourceLocation, Material, TextureAtlasSprite> getter, CallbackInfo ci) {
this.ignoreModelLoad = false;
textureGetter = getter;
DynamicBakedModelProvider.currentInstance = (DynamicBakedModelProvider)this.bakedTopLevelModels;
}
@Redirect(method = "bakeModels", at = @At(value = "INVOKE", target = "Ljava/util/Map;keySet()Ljava/util/Set;"))
private Set<ResourceLocation> skipBake(Map<ResourceLocation, UnbakedModel> instance) {
Set<ResourceLocation> modelSet = new HashSet<>(instance.keySet());
if(modelSet.size() > 0)
ModernFix.LOGGER.info("Early baking {} models", modelSet.size());
return modelSet;
}
/**
* Use the already loaded missing model instead of the cache entry (which will probably get evicted).
*/
@Redirect(method = "loadModel", at = @At(value = "INVOKE", target = "Ljava/util/Map;get(Ljava/lang/Object;)Ljava/lang/Object;", ordinal = 1))
private Object getMissingModel(Map map, Object rl) {
if(rl == MISSING_MODEL_LOCATION && map == unbakedCache)
return missingModel;
return unbakedCache.get(rl);
}
@ModifyVariable(method = "cacheAndQueueDependencies", at = @At("HEAD"), argsOnly = true)
private UnbakedModel fireUnbakedEvent(UnbakedModel model, ResourceLocation location) {
for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) {
try {
model = integration.onUnbakedModelLoad(location, model, (ModelBakery)(Object)this);
} catch(RuntimeException e) {
ModernFix.LOGGER.error("Exception firing model load event for {}", location, e);
}
}
return model;
}
@Inject(method = "cacheAndQueueDependencies", at = @At("RETURN"))
private void addToSmallLoadingCache(ResourceLocation location, UnbakedModel model, CallbackInfo ci) {
smallLoadingCache.put(location, model);
}
private int mfix$nestedLoads = 0;
/**
* @author embeddedt
* @reason synchronize
*/
@Inject(method = "getModel", at = @At("HEAD"), cancellable = true)
public void getOrLoadModelDynamic(ResourceLocation modelLocation, CallbackInfoReturnable<UnbakedModel> cir) {
if(modelLocation.equals(MISSING_MODEL_LOCATION)) {
cir.setReturnValue(missingModel);
return;
}
UnbakedModel existing = this.unbakedCache.get(modelLocation);
if (existing != null) {
cir.setReturnValue(existing);
} else {
synchronized(this) {
if (this.loadingStack.contains(modelLocation)) {
throw new IllegalStateException("Circular reference while loading " + modelLocation);
} else {
this.loadingStack.add(modelLocation);
UnbakedModel iunbakedmodel = missingModel;
while(!this.loadingStack.isEmpty()) {
ResourceLocation resourcelocation = this.loadingStack.iterator().next();
mfix$nestedLoads++;
try {
existing = this.unbakedCache.get(resourcelocation);
if (existing == null) {
if(debugDynamicModelLoading)
LOGGER.info("Loading {}", resourcelocation);
this.loadModel(resourcelocation);
} else
smallLoadingCache.put(resourcelocation, existing);
} catch (ModelBakery.BlockStateDefinitionException var9) {
LOGGER.warn(var9.getMessage());
this.unbakedCache.put(resourcelocation, iunbakedmodel);
smallLoadingCache.put(resourcelocation, iunbakedmodel);
} catch (Exception var10) {
LOGGER.warn("Unable to load model: '{}' referenced from: {}: {}", resourcelocation, modelLocation, var10);
this.unbakedCache.put(resourcelocation, iunbakedmodel);
smallLoadingCache.put(resourcelocation, iunbakedmodel);
} finally {
mfix$nestedLoads--;
this.loadingStack.remove(resourcelocation);
}
}
// We have to get the result from the temporary cache used for a model load
// As in pathological cases (e.g. Pedestals on 1.19) unbakedCache can lose
// the model immediately
UnbakedModel result = smallLoadingCache.getOrDefault(modelLocation, iunbakedmodel);
try {
// required as some mods (e.g. EBE) call bake directly on the returned model, without resolving parents themselves
result.resolveParents(this::getModel);
} catch(RuntimeException ignored) {}
// We are done with loading, so clear this cache to allow GC of any unneeded models
if(mfix$nestedLoads == 0)
smallLoadingCache.clear();
cir.setReturnValue(result);
}
}
}
}
private <T extends Comparable<T>, V extends T> BlockState setPropertyGeneric(BlockState state, Property<T> prop, Object o) {
return state.setValue(prop, (V)o);
}
@Redirect(method = "loadModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/StateDefinition;getPossibleStates()Lcom/google/common/collect/ImmutableList;"))
private ImmutableList<BlockState> loadOnlyRelevantBlockState(StateDefinition<Block, BlockState> stateDefinition, ResourceLocation location) {
if(!(location instanceof ModelResourceLocation) || Minecraft.getInstance().level == null)
return stateDefinition.getPossibleStates();
return ModelBakeryHelpers.getBlockStatesForMRL(stateDefinition, (ModelResourceLocation)location);
}
@Override
public BakedModel bakeDefault(ResourceLocation modelLocation, ModelState state) {
ModelBakery.BakedCacheKey key = new ModelBakery.BakedCacheKey(modelLocation, BlockModelRotation.X0_Y0.getRotation(), BlockModelRotation.X0_Y0.isUvLocked());
BakedModel m = loadedBakedModels.getIfPresent(key);
if(m != null)
return m;
ModelBakery self = (ModelBakery) (Object) this;
ModelBaker theBaker = self.new ModelBakerImpl(textureGetter, modelLocation);
((IExtendedModelBaker)theBaker).throwOnMissingModel(true);
synchronized(this) { m = theBaker.bake(modelLocation, state, theBaker.getModelTextureGetter()); }
if(m != null)
loadedBakedModels.put(key, m);
return m;
}
@Override
public ImmutableList<BlockState> getBlockStatesForMRL(StateDefinition<Block, BlockState> stateDefinition, ModelResourceLocation location) {
return loadOnlyRelevantBlockState(stateDefinition, location);
}
private BakedModel bakedMissingModel = null;
public void setBakedMissingModel(BakedModel m) {
bakedMissingModel = m;
}
public BakedModel getBakedMissingModel() {
return bakedMissingModel;
}
public UnbakedModel mfix$getUnbakedMissingModel() {
return missingModel;
}
}

View File

@ -1,123 +0,0 @@
package org.embeddedt.modernfix.neoforge.mixin.perf.dynamic_resources.ctm;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.*;
import net.minecraft.resources.ResourceLocation;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.annotation.RequiresMod;
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
import org.embeddedt.modernfix.neoforge.dynresources.IModelBakerImpl;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import team.chisel.ctm.CTM;
import team.chisel.ctm.api.model.IModelCTM;
import team.chisel.ctm.client.model.AbstractCTMBakedModel;
import team.chisel.ctm.client.model.ModelCTM;
import team.chisel.ctm.client.texture.IMetadataSectionCTM;
import team.chisel.ctm.client.util.ResourceUtil;
import team.chisel.ctm.client.util.TextureMetadataHandler;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.util.*;
import java.util.function.Function;
@Mixin(TextureMetadataHandler.class)
@RequiresMod("ctm")
@ClientOnlyMixin
public abstract class TextureMetadataHandlerMixin implements ModernFixClientIntegration {
@Shadow(remap = false) @Nonnull protected abstract BakedModel wrap(UnbakedModel model, BakedModel object) throws IOException;
@Shadow @Final private Multimap<ResourceLocation, Material> scrapedTextures;
@Inject(method = "<init>", at = @At("RETURN"))
private void subscribeDynamic(CallbackInfo ci) {
ModernFixClient.CLIENT_INTEGRATIONS.add(this);
}
@Inject(method = { "onModelBake(Lnet/neoforged/neoforge/client/event/ModelEvent$ModifyBakingResult;)V", "onModelBake(Lnet/neoforged/neoforge/client/event/ModelEvent$BakingCompleted;)V" }, at = @At("HEAD"), cancellable = true, remap = false)
private void noIteration(CallbackInfo ci) {
ci.cancel();
}
@Override
public BakedModel onBakedModelLoad(ResourceLocation rl, UnbakedModel rootModel, BakedModel baked, ModelState state, ModelBakery bakery) {
if (rl instanceof ModelResourceLocation && !(baked instanceof AbstractCTMBakedModel) && !baked.isCustomRenderer()) {
Deque<ResourceLocation> dependencies = new ArrayDeque<>();
Set<ResourceLocation> seenModels = new HashSet<>();
dependencies.push(rl);
seenModels.add(rl);
boolean shouldWrap = false;
Set<Pair<String, String>> errors = new HashSet<>();
// Breadth-first loop through dependencies, exiting as soon as a CTM texture is found, and skipping duplicates/cycles
while (!shouldWrap && !dependencies.isEmpty()) {
ResourceLocation dep = dependencies.pop();
UnbakedModel model;
try {
model = dep == rl ? rootModel : bakery.getModel(dep);
} catch (Exception e) {
continue;
}
Collection<Material> textures = Sets.newHashSet(scrapedTextures.get(dep));
Collection<ResourceLocation> newDependencies = model.getDependencies();
for (Material tex : textures) {
IMetadataSectionCTM meta = null;
// Cache all dependent texture metadata
try {
meta = ResourceUtil.getMetadata(ResourceUtil.spriteToAbsolute(tex.texture())).orElse(null); // TODO, lazy
} catch (IOException e) {} // Fallthrough
if (meta != null) {
// At least one texture has CTM metadata, so we should wrap this model
shouldWrap = true;
}
}
for (ResourceLocation newDep : newDependencies) {
if (seenModels.add(newDep)) {
dependencies.push(newDep);
}
}
}
if (shouldWrap) {
try {
baked = wrap(rootModel, baked);
handleInit(rl, baked, bakery);
dependencies.clear();
} catch (IOException e) {
CTM.logger.error("Could not wrap model " + rl + ". Aborting...", e);
}
}
}
return baked;
}
private void handleInit(ResourceLocation key, BakedModel wrappedModel, ModelBakery bakery) {
if(wrappedModel instanceof AbstractCTMBakedModel baked) {
IModelCTM var10 = baked.getModel();
if (var10 instanceof ModelCTM ctmModel) {
if (!ctmModel.isInitialized()) {
Function<Material, TextureAtlasSprite> spriteGetter = (m) -> {
return Minecraft.getInstance().getModelManager().getAtlas(m.atlasLocation()).getSprite(m.texture());
};
ModelBakery.ModelBakerImpl baker = bakery.new ModelBakerImpl((rl, m) -> {
return m.sprite();
}, key);
// bypass bakedCache so that dependent models get re-baked and thus retrieve their sprites again
((IModelBakerImpl)baker).mfix$ignoreCache();
ctmModel.bake(baker, spriteGetter, BlockModelRotation.X0_Y0, key);
}
}
}
}
}

View File

@ -1,38 +0,0 @@
package org.embeddedt.modernfix.neoforge.mixin.perf.dynamic_resources.rs;
import com.refinedmods.refinedstorage.render.BakedModelOverrideRegistry;
import com.refinedmods.refinedstorage.setup.ClientSetup;
import net.minecraft.client.resources.model.*;
import net.minecraft.resources.ResourceLocation;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.annotation.RequiresMod;
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ClientSetup.class)
@RequiresMod("refinedstorage")
@ClientOnlyMixin
public class ClientSetupMixin {
@Shadow(remap = false) @Final private static BakedModelOverrideRegistry BAKED_MODEL_OVERRIDE_REGISTRY;
@Inject(method = "registerBakedModelOverrides", at = @At("RETURN"), remap = false)
private static void addDynamicListener(CallbackInfo ci) {
ModernFixClient.CLIENT_INTEGRATIONS.add(new ModernFixClientIntegration() {
@Override
public BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery) {
BakedModelOverrideRegistry.BakedModelOverrideFactory factory = BAKED_MODEL_OVERRIDE_REGISTRY.get(location instanceof ModelResourceLocation ? new ResourceLocation(location.getNamespace(), location.getPath()) : location);
if(factory != null)
return factory.create(originalModel, bakery.getBakedTopLevelModels());
else
return originalModel;
}
});
}
}

View File

@ -1,64 +0,0 @@
package org.embeddedt.modernfix.neoforge.mixin.perf.dynamic_resources.supermartijncore;
import com.supermartijn642.core.registry.ClientRegistrationHandler;
import com.supermartijn642.core.util.Pair;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.ModelState;
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.resources.ResourceLocation;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.annotation.RequiresMod;
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
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.callback.CallbackInfo;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
@Mixin(ClientRegistrationHandler.class)
@RequiresMod("supermartijn642corelib")
@ClientOnlyMixin
public class ClientRegistrationHandlerMixin {
@Shadow(remap = false) @Final private List<Pair<Supplier<Stream<ResourceLocation>>, Function<BakedModel, BakedModel>>> modelOverwrites;
private Map<ResourceLocation, Function<BakedModel, BakedModel>> modelOverwritesByLocation = new Object2ObjectOpenHashMap<>();
@Redirect(method = "handleModelBakeEvent", at = @At(value = "FIELD", target = "Lcom/supermartijn642/core/registry/ClientRegistrationHandler;modelOverwrites:Ljava/util/List;"), remap = false)
private List<?> skipModelOverwrites(ClientRegistrationHandler h) {
modelOverwritesByLocation.clear();
for(Pair<Supplier<Stream<ResourceLocation>>, Function<BakedModel, BakedModel>> pair : this.modelOverwrites) {
Stream<ResourceLocation> locationStream = pair.left().get();
Function<BakedModel, BakedModel> swapper = pair.right();
locationStream.forEach(l -> {
modelOverwritesByLocation.put(l, swapper);
});
}
return Collections.emptyList();
}
@Inject(method = "<init>", at = @At("RETURN"))
private void registerDynBake(String modid, CallbackInfo ci) {
ModernFixClient.CLIENT_INTEGRATIONS.add(new ModernFixClientIntegration() {
@Override
public BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery) {
Function<BakedModel, BakedModel> replacer = modelOverwritesByLocation.get(location);
if(replacer != null)
return replacer.apply(originalModel);
else
return originalModel;
}
});
}
}

View File

@ -3,13 +3,10 @@ package org.embeddedt.modernfix.platform.neoforge;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.client.searchtree.SearchRegistry;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.fml.ModLoader;
import net.neoforged.fml.ModLoadingIssue;
@ -17,7 +14,6 @@ import net.neoforged.fml.loading.FMLLoader;
import net.neoforged.fml.loading.FMLPaths;
import net.neoforged.fml.loading.LoadingModList;
import net.neoforged.fml.loading.moddiscovery.ModInfo;
import net.neoforged.neoforge.client.CreativeModeTabSearchRegistry;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.RegisterCommandsEvent;
import net.neoforged.neoforge.network.PacketDistributor;
@ -145,23 +141,6 @@ public class ModernFixPlatformHooksImpl implements ModernFixPlatformHooks {
return modOptions;
}
public void registerCreativeSearchTrees(SearchRegistry registry, SearchRegistry.TreeBuilderSupplier<ItemStack> nameSupplier, SearchRegistry.TreeBuilderSupplier<ItemStack> tagSupplier, BiConsumer<SearchRegistry.Key<ItemStack>, List<ItemStack>> populator) {
for (SearchRegistry.Key<ItemStack> nameKey : CreativeModeTabSearchRegistry.getNameSearchKeys().values()) {
registry.register(nameKey, nameSupplier);
}
for (SearchRegistry.Key<ItemStack> tagKey : CreativeModeTabSearchRegistry.getTagSearchKeys().values()) {
registry.register(tagKey, tagSupplier);
}
Map<CreativeModeTab, SearchRegistry.Key<ItemStack>> tagSearchKeys = CreativeModeTabSearchRegistry.getTagSearchKeys();
CreativeModeTabSearchRegistry.getNameSearchKeys().forEach((tab, nameSearchKey) -> {
SearchRegistry.Key<ItemStack> tagSearchKey = tagSearchKeys.get(tab);
tab.setSearchTreeBuilder((contents) -> {
populator.accept(nameSearchKey, contents);
populator.accept(tagSearchKey, contents);
});
});
}
public void onLaunchComplete() {
if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.spark_profile_launch.OnForge")) {
CommonModUtil.runWithoutCrash(() -> SparkLaunchProfiler.stop("launch"), "Failed to stop profiler");

View File

@ -47,7 +47,7 @@ modId = "neoforge" #mandatory
# Does this dependency have to exist - if not, ordering below must be specified
type = "required" #mandatory
# The version range of the dependency
versionRange = "[20.6.100-beta,)" #mandatory
versionRange = "[21.0.0-alpha,)" #mandatory
# An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory
ordering = "NONE"
# Side this dependency is applied on - BOTH, CLIENT or SERVER
@ -57,7 +57,7 @@ side = "BOTH"
modId = "minecraft"
type = "required"
# This version range declares a minimum of the current minecraft version up to but not including the next major version
versionRange = "[1.20, 1.21)"
versionRange = "[1.21, 1.22)"
ordering = "NONE"
side = "BOTH"
[[dependencies.modernfix]]