Enable NeoForge project
This commit is contained in:
parent
9d584d13d2
commit
6e9dfaf0c6
|
|
@ -1,12 +1,5 @@
|
||||||
package org.embeddedt.modernfix.api.entrypoint;
|
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
|
* 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.
|
* to integrate with ModernFix's features.
|
||||||
|
|
@ -20,58 +13,4 @@ public interface ModernFixClientIntegration {
|
||||||
*/
|
*/
|
||||||
default void onDynamicResourcesStatusChange(boolean enabled) {
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import org.embeddedt.modernfix.searchtree.RecipeBookSearchTree;
|
||||||
import org.embeddedt.modernfix.searchtree.SearchTreeProviderRegistry;
|
import org.embeddedt.modernfix.searchtree.SearchTreeProviderRegistry;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
import org.lwjgl.glfw.GLFWErrorCallback;
|
import org.lwjgl.glfw.GLFWErrorCallback;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
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;
|
||||||
|
|
@ -28,6 +29,8 @@ import java.util.concurrent.CompletableFuture;
|
||||||
public abstract class SessionSearchTreesMixin {
|
public abstract class SessionSearchTreesMixin {
|
||||||
@Shadow private CompletableFuture<SearchTree<RecipeCollection>> recipeSearch;
|
@Shadow private CompletableFuture<SearchTree<RecipeCollection>> recipeSearch;
|
||||||
@Shadow private CompletableFuture<SearchTree<ItemStack>> creativeByNameSearch;
|
@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;
|
private SearchTreeProviderRegistry.Provider mfix$provider;
|
||||||
|
|
||||||
@Inject(method = "<init>", at = @At("RETURN"))
|
@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)
|
@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 useSearchModItems(Runnable r) {
|
private Runnable useOverridenSearchTreeLogic(SessionSearchTrees.Key key, Runnable r) {
|
||||||
if(mfix$provider == null) {
|
if(mfix$provider == null) {
|
||||||
return r;
|
return r;
|
||||||
} else {
|
}
|
||||||
|
if(key == CREATIVE_NAMES) {
|
||||||
return () -> {
|
return () -> {
|
||||||
CompletableFuture<?> old = this.creativeByNameSearch;
|
CompletableFuture<?> old = this.creativeByNameSearch;
|
||||||
this.creativeByNameSearch = CompletableFuture.supplyAsync(() -> {
|
this.creativeByNameSearch = CompletableFuture.supplyAsync(() -> {
|
||||||
|
|
@ -76,13 +80,7 @@ public abstract class SessionSearchTreesMixin {
|
||||||
old.cancel(true);
|
old.cancel(true);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
if(key == CREATIVE_TAGS) {
|
||||||
|
|
||||||
@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 {
|
|
||||||
return () -> {
|
return () -> {
|
||||||
CompletableFuture<?> old = this.creativeByNameSearch;
|
CompletableFuture<?> old = this.creativeByNameSearch;
|
||||||
this.creativeByNameSearch = CompletableFuture.supplyAsync(() -> {
|
this.creativeByNameSearch = CompletableFuture.supplyAsync(() -> {
|
||||||
|
|
@ -91,5 +89,6 @@ public abstract class SessionSearchTreesMixin {
|
||||||
old.cancel(true);
|
old.cancel(true);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,13 @@ package org.embeddedt.modernfix.dynamicresources;
|
||||||
|
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.mojang.datafixers.util.Pair;
|
|
||||||
import net.minecraft.client.resources.model.*;
|
import net.minecraft.client.resources.model.*;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.block.state.StateDefinition;
|
import net.minecraft.world.level.block.state.StateDefinition;
|
||||||
import net.minecraft.world.level.block.state.properties.Property;
|
import net.minecraft.world.level.block.state.properties.Property;
|
||||||
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.BiFunction;
|
|
||||||
|
|
||||||
public class ModelBakeryHelpers {
|
public class ModelBakeryHelpers {
|
||||||
/**
|
/**
|
||||||
|
|
@ -108,13 +104,4 @@ public class ModelBakeryHelpers {
|
||||||
}
|
}
|
||||||
return ImmutableList.copyOf(finalList);
|
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));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,3 +39,4 @@ accessible field net/minecraft/client/renderer/block/model/ItemOverrides$BakedOv
|
||||||
mutable 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 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
|
||||||
|
|
@ -5,9 +5,10 @@ junit_version=5.10.0-M1
|
||||||
mixinextras_version=0.3.2
|
mixinextras_version=0.3.2
|
||||||
|
|
||||||
mod_id=modernfix
|
mod_id=modernfix
|
||||||
minecraft_version=1.21-pre3
|
minecraft_version=1.21-pre4
|
||||||
enabled_platforms=fabric
|
enabled_platforms=fabric,neoforge
|
||||||
forge_version=20.6.100-beta
|
forge_version=21.0.0-alpha.1.21-pre4.20240609.000029
|
||||||
|
neoforge_pr=1076
|
||||||
# parchment_version=2023.07.09
|
# parchment_version=2023.07.09
|
||||||
refined_storage_version=4392788
|
refined_storage_version=4392788
|
||||||
jei_version=16.0.0.28
|
jei_version=16.0.0.28
|
||||||
|
|
@ -15,7 +16,7 @@ rei_version=13.0.678
|
||||||
ctm_version=1.20.1-1.1.8+4
|
ctm_version=1.20.1-1.1.8+4
|
||||||
kubejs_version=1902.6.0-build.142
|
kubejs_version=1902.6.0-build.142
|
||||||
rhino_version=1902.2.2-build.268
|
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_loader_version=0.15.11
|
||||||
fabric_api_version=0.100.0+1.21
|
fabric_api_version=0.100.0+1.21
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,15 @@ repositories {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
maven { url "https://maven.neoforged.net" }
|
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 {
|
dependencies {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ public class ModernFixConfig {
|
||||||
|
|
||||||
public static Set<ResourceLocation> getJeiPluginBlacklist() {
|
public static Set<ResourceLocation> getJeiPluginBlacklist() {
|
||||||
if(jeiPluginBlacklist == null) {
|
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;
|
return jeiPluginBlacklist;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,10 @@ public class ModelBakeEventHelper {
|
||||||
"vampirism",
|
"vampirism",
|
||||||
"elevatorid",
|
"elevatorid",
|
||||||
"embers");
|
"embers");
|
||||||
private final Map<ResourceLocation, BakedModel> modelRegistry;
|
private final Map<ModelResourceLocation, BakedModel> modelRegistry;
|
||||||
private final Set<ResourceLocation> topLevelModelLocations;
|
private final Set<ModelResourceLocation> topLevelModelLocations;
|
||||||
private final MutableGraph<String> dependencyGraph;
|
private final MutableGraph<String> dependencyGraph;
|
||||||
public ModelBakeEventHelper(Map<ResourceLocation, BakedModel> modelRegistry) {
|
public ModelBakeEventHelper(Map<ModelResourceLocation, BakedModel> modelRegistry) {
|
||||||
this.modelRegistry = modelRegistry;
|
this.modelRegistry = modelRegistry;
|
||||||
this.topLevelModelLocations = new HashSet<>(modelRegistry.keySet());
|
this.topLevelModelLocations = new HashSet<>(modelRegistry.keySet());
|
||||||
// Skip going through ModelLocationCache because most of the accesses will be misses
|
// 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
|
* @param modId the mod that the event is being fired for
|
||||||
* @return a wrapper around the model registry
|
* @return a wrapper around the model registry
|
||||||
*/
|
*/
|
||||||
private Map<ResourceLocation, BakedModel> createWarningRegistry(String modId) {
|
private Map<ModelResourceLocation, BakedModel> createWarningRegistry(String modId) {
|
||||||
return new ForwardingInclDefaultsMap<ResourceLocation, BakedModel>() {
|
return new ForwardingInclDefaultsMap<ModelResourceLocation, BakedModel>() {
|
||||||
@Override
|
@Override
|
||||||
protected Map<ResourceLocation, BakedModel> delegate() {
|
protected Map<ModelResourceLocation, BakedModel> delegate() {
|
||||||
return modelRegistry;
|
return modelRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,13 +89,13 @@ public class ModelBakeEventHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<ResourceLocation> keySet() {
|
public Set<ModelResourceLocation> keySet() {
|
||||||
logWarning();
|
logWarning();
|
||||||
return super.keySet();
|
return super.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Entry<ResourceLocation, BakedModel>> entrySet() {
|
public Set<Entry<ModelResourceLocation, BakedModel>> entrySet() {
|
||||||
logWarning();
|
logWarning();
|
||||||
return super.entrySet();
|
return super.entrySet();
|
||||||
}
|
}
|
||||||
|
|
@ -107,14 +107,14 @@ public class ModelBakeEventHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void replaceAll(BiFunction<? super ResourceLocation, ? super BakedModel, ? extends BakedModel> function) {
|
public void replaceAll(BiFunction<? super ModelResourceLocation, ? super BakedModel, ? extends BakedModel> function) {
|
||||||
logWarning();
|
logWarning();
|
||||||
super.replaceAll(function);
|
super.replaceAll(function);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<ResourceLocation, BakedModel> wrapRegistry(String modId) {
|
public Map<ModelResourceLocation, BakedModel> wrapRegistry(String modId) {
|
||||||
final Set<String> modIdsToInclude = new HashSet<>();
|
final Set<String> modIdsToInclude = new HashSet<>();
|
||||||
modIdsToInclude.add(modId);
|
modIdsToInclude.add(modId);
|
||||||
try {
|
try {
|
||||||
|
|
@ -123,11 +123,11 @@ public class ModelBakeEventHelper {
|
||||||
modIdsToInclude.remove("minecraft");
|
modIdsToInclude.remove("minecraft");
|
||||||
if(modIdsToInclude.stream().noneMatch(INCOMPATIBLE_MODS::contains))
|
if(modIdsToInclude.stream().noneMatch(INCOMPATIBLE_MODS::contains))
|
||||||
return createWarningRegistry(modId);
|
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);
|
BakedModel missingModel = modelRegistry.get(ModelBakery.MISSING_MODEL_LOCATION);
|
||||||
return new ForwardingMap<ResourceLocation, BakedModel>() {
|
return new ForwardingMap<ModelResourceLocation, BakedModel>() {
|
||||||
@Override
|
@Override
|
||||||
protected Map<ResourceLocation, BakedModel> delegate() {
|
protected Map<ModelResourceLocation, BakedModel> delegate() {
|
||||||
return modelRegistry;
|
return modelRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -142,7 +142,7 @@ public class ModelBakeEventHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<ResourceLocation> keySet() {
|
public Set<ModelResourceLocation> keySet() {
|
||||||
return ourModelLocations;
|
return ourModelLocations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -152,10 +152,10 @@ public class ModelBakeEventHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
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());
|
List<ModelResourceLocation> locations = new ArrayList<>(keySet());
|
||||||
for(ResourceLocation location : locations) {
|
for(ModelResourceLocation location : locations) {
|
||||||
/*
|
/*
|
||||||
* Fetching every model is insanely slow. So we call the function with a null object first, since it
|
* 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
|
* probably isn't expecting that. If we get an exception thrown, or it returns nonnull, then we know
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ public class ModernFixForge {
|
||||||
event.register(Registries.ITEM, helper -> {
|
event.register(Registries.ITEM, helper -> {
|
||||||
Item.Properties props = new Item.Properties();
|
Item.Properties props = new Item.Properties();
|
||||||
for(int i = 0; i < 1000000; i++) {
|
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));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,7 +2,7 @@ package org.embeddedt.modernfix.neoforge.mixin.perf.dynamic_resources;
|
||||||
|
|
||||||
import com.google.common.base.Stopwatch;
|
import com.google.common.base.Stopwatch;
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
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.bus.api.Event;
|
||||||
import net.neoforged.fml.ModContainer;
|
import net.neoforged.fml.ModContainer;
|
||||||
import net.neoforged.fml.ModList;
|
import net.neoforged.fml.ModList;
|
||||||
|
|
@ -33,7 +33,7 @@ public class ForgeHooksClientMixin {
|
||||||
ModelBakeEventHelper helper = new ModelBakeEventHelper(bakeEvent.getModels());
|
ModelBakeEventHelper helper = new ModelBakeEventHelper(bakeEvent.getModels());
|
||||||
Method acceptEv = ObfuscationReflectionHelper.findMethod(ModContainer.class, "acceptEvent", Event.class);
|
Method acceptEv = ObfuscationReflectionHelper.findMethod(ModContainer.class, "acceptEvent", Event.class);
|
||||||
ModList.get().forEachModContainer((id, mc) -> {
|
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());
|
ModelEvent.ModifyBakingResult postedEvent = new ModelEvent.ModifyBakingResult(newRegistry, bakeEvent.getTextureGetter(), bakeEvent.getModelBakery());
|
||||||
Stopwatch timer = Stopwatch.createStarted();
|
Stopwatch timer = Stopwatch.createStarted();
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ public abstract class ItemModelMesherForgeMixin extends ItemModelShaper {
|
||||||
super(arg);
|
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"))
|
@Inject(method = "<init>", at = @At("RETURN"))
|
||||||
private void replaceLocationMap(CallbackInfo ci) {
|
private void replaceLocationMap(CallbackInfo ci) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -3,13 +3,10 @@ package org.embeddedt.modernfix.platform.neoforge;
|
||||||
import com.google.common.collect.ArrayListMultimap;
|
import com.google.common.collect.ArrayListMultimap;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.mojang.brigadier.CommandDispatcher;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
import net.minecraft.client.searchtree.SearchRegistry;
|
|
||||||
import net.minecraft.commands.CommandSourceStack;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
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.api.distmarker.Dist;
|
||||||
import net.neoforged.fml.ModLoader;
|
import net.neoforged.fml.ModLoader;
|
||||||
import net.neoforged.fml.ModLoadingIssue;
|
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.FMLPaths;
|
||||||
import net.neoforged.fml.loading.LoadingModList;
|
import net.neoforged.fml.loading.LoadingModList;
|
||||||
import net.neoforged.fml.loading.moddiscovery.ModInfo;
|
import net.neoforged.fml.loading.moddiscovery.ModInfo;
|
||||||
import net.neoforged.neoforge.client.CreativeModeTabSearchRegistry;
|
|
||||||
import net.neoforged.neoforge.common.NeoForge;
|
import net.neoforged.neoforge.common.NeoForge;
|
||||||
import net.neoforged.neoforge.event.RegisterCommandsEvent;
|
import net.neoforged.neoforge.event.RegisterCommandsEvent;
|
||||||
import net.neoforged.neoforge.network.PacketDistributor;
|
import net.neoforged.neoforge.network.PacketDistributor;
|
||||||
|
|
@ -145,23 +141,6 @@ public class ModernFixPlatformHooksImpl implements ModernFixPlatformHooks {
|
||||||
return modOptions;
|
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() {
|
public void onLaunchComplete() {
|
||||||
if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.spark_profile_launch.OnForge")) {
|
if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.spark_profile_launch.OnForge")) {
|
||||||
CommonModUtil.runWithoutCrash(() -> SparkLaunchProfiler.stop("launch"), "Failed to stop profiler");
|
CommonModUtil.runWithoutCrash(() -> SparkLaunchProfiler.stop("launch"), "Failed to stop profiler");
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ modId = "neoforge" #mandatory
|
||||||
# Does this dependency have to exist - if not, ordering below must be specified
|
# Does this dependency have to exist - if not, ordering below must be specified
|
||||||
type = "required" #mandatory
|
type = "required" #mandatory
|
||||||
# The version range of the dependency
|
# 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
|
# An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory
|
||||||
ordering = "NONE"
|
ordering = "NONE"
|
||||||
# Side this dependency is applied on - BOTH, CLIENT or SERVER
|
# Side this dependency is applied on - BOTH, CLIENT or SERVER
|
||||||
|
|
@ -57,7 +57,7 @@ side = "BOTH"
|
||||||
modId = "minecraft"
|
modId = "minecraft"
|
||||||
type = "required"
|
type = "required"
|
||||||
# This version range declares a minimum of the current minecraft version up to but not including the next major version
|
# 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"
|
ordering = "NONE"
|
||||||
side = "BOTH"
|
side = "BOTH"
|
||||||
[[dependencies.modernfix]]
|
[[dependencies.modernfix]]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user