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

This commit is contained in:
embeddedt 2023-05-22 14:24:27 -04:00
commit 31feef398f
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
26 changed files with 351 additions and 167 deletions

View File

@ -11,6 +11,8 @@ import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.util.MemoryReserve; import net.minecraft.util.MemoryReserve;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import org.embeddedt.modernfix.api.constants.IntegrationConstants;
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
import org.embeddedt.modernfix.core.ModernFixMixinPlugin; import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
import org.embeddedt.modernfix.packet.EntityIDSyncPacket; import org.embeddedt.modernfix.packet.EntityIDSyncPacket;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks; import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
@ -22,6 +24,7 @@ import org.embeddedt.modernfix.world.IntegratedWatchdog;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.*; import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class ModernFixClient { public class ModernFixClient {
public static long worldLoadStartTime; public static long worldLoadStartTime;
@ -33,6 +36,11 @@ public class ModernFixClient {
public String brandingString = null; public String brandingString = null;
/**
* The list of loaded client integrations.
*/
public static List<ModernFixClientIntegration> CLIENT_INTEGRATIONS = new CopyOnWriteArrayList<>();
public ModernFixClient() { public ModernFixClient() {
// clear reserve as it's not needed // clear reserve as it's not needed
MemoryReserve.release(); MemoryReserve.release();
@ -41,6 +49,13 @@ public class ModernFixClient {
} }
SearchTreeProviderRegistry.register(JEIBackedSearchTree.PROVIDER); SearchTreeProviderRegistry.register(JEIBackedSearchTree.PROVIDER);
SearchTreeProviderRegistry.register(REIBackedSearchTree.PROVIDER); SearchTreeProviderRegistry.register(REIBackedSearchTree.PROVIDER);
for(String className : ModernFixPlatformHooks.getCustomModOptions().get(IntegrationConstants.CLIENT_INTEGRATION_CLASS)) {
try {
CLIENT_INTEGRATIONS.add((ModernFixClientIntegration)Class.forName(className).getDeclaredConstructor().newInstance());
} catch(ReflectiveOperationException | ClassCastException e) {
ModernFix.LOGGER.error("Could not instantiate integration {}", className, e);
}
}
} }
public void resetWorldLoadStateMachine() { public void resetWorldLoadStateMachine() {

View File

@ -0,0 +1,8 @@
package org.embeddedt.modernfix.api.constants;
public class IntegrationConstants {
public static final String INTEGRATIONS_KEY = "modernfix:integration";
public static final String CLIENT_INTEGRATION_CLASS = "client_entrypoint";
public static final String INTEGRATION_CLASS = "entrypoint";
}

View File

@ -0,0 +1,49 @@
package org.embeddedt.modernfix.api.entrypoint;
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;
/**
* 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.
*/
public interface ModernFixClientIntegration {
/**
* Called when the dynamic resources status has changed during a model reload so mods know whether to run their
* normal codepath or the dynamic version.
*
* @param enabled whether dynamic resources is 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 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
*/
default BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery) {
return originalModel;
}
}

View File

@ -0,0 +1,74 @@
package org.embeddedt.modernfix.api.helpers;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.resources.model.*;
import net.minecraft.core.registries.BuiltInRegistries;
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 org.embeddedt.modernfix.duck.IExtendedModelBakery;
import org.embeddedt.modernfix.dynamicresources.ModelBakeryHelpers;
import org.embeddedt.modernfix.util.DynamicMap;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiFunction;
@SuppressWarnings("unused")
public final class ModelHelpers {
/**
* Allows converting a ModelResourceLocation back into the corresponding BlockState(s). Try to avoid calling this
* multiple times if possible.
* @param location the location of the model
* @return a list of all blockstates related to the model
*/
public static ImmutableList<BlockState> getBlockStateForLocation(ModelResourceLocation location) {
Optional<Block> blockOpt = BuiltInRegistries.BLOCK.getOptional(new ResourceLocation(location.getNamespace(), location.getPath()));
if(blockOpt.isPresent())
return ModelBakeryHelpers.getBlockStatesForMRL(blockOpt.get().getStateDefinition(), location);
else
return ImmutableList.of();
}
/**
* Allows converting a ModelResourceLocation back into the corresponding BlockState(s). Faster version of its
* companion function if and only if you know the corresponding Block already for some reason.
* @param definition the state definition for the Block
* @param location the location of the model
* @return a list of all blockstates related to the model
*/
public static ImmutableList<BlockState> getBlockStateForLocation(StateDefinition<Block, BlockState> definition, ModelResourceLocation location) {
return ModelBakeryHelpers.getBlockStatesForMRL(definition, location);
}
/**
* Compatibility helper for mods to use to get a map-like view of the model bakery.
* @param modelGetter the model getter function supplied by the integration class
* @return a fake map of the top-level models
*/
public static Map<ResourceLocation, BakedModel> createFakeTopLevelMap(BiFunction<ResourceLocation, ModelState, BakedModel> modelGetter) {
return new DynamicMap<>(location -> modelGetter.apply(location, BlockModelRotation.X0_Y0));
}
/**
* Provides a ModelBaker for mods to use.
* @param bakery the ModelBakery supplied to your integration
* @return an appropriate ModelBaker
*/
public static ModelBaker adaptBakery(ModelBakery bakery) {
return new ModelBaker() {
@Override
public UnbakedModel getModel(ResourceLocation resourceLocation) {
return bakery.getModel(resourceLocation);
}
@Nullable
@Override
public BakedModel bake(ResourceLocation resourceLocation, ModelState modelState) {
return ((IExtendedModelBakery)bakery).bakeDefault(resourceLocation, modelState);
}
};
}
}

View File

@ -1,5 +1,6 @@
package org.embeddedt.modernfix.common.mixin.perf.blast_search_trees; package org.embeddedt.modernfix.common.mixin.perf.blast_search_trees;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.searchtree.SearchRegistry; import net.minecraft.client.searchtree.SearchRegistry;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@ -8,6 +9,8 @@ import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks; import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import org.embeddedt.modernfix.searchtree.DummySearchTree; import org.embeddedt.modernfix.searchtree.DummySearchTree;
import org.embeddedt.modernfix.searchtree.SearchTreeProviderRegistry; 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.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;
@ -36,6 +39,14 @@ public abstract class MinecraftMixin {
this.searchRegistry.register(SearchRegistry.CREATIVE_TAGS, tagSupplier); this.searchRegistry.register(SearchRegistry.CREATIVE_TAGS, tagSupplier);
this.searchRegistry.register(SearchRegistry.RECIPE_COLLECTIONS, list -> new DummySearchTree<>()); this.searchRegistry.register(SearchRegistry.RECIPE_COLLECTIONS, list -> new DummySearchTree<>());
ModernFixPlatformHooks.registerCreativeSearchTrees(this.searchRegistry, nameSupplier, tagSupplier, this::populateSearchTree); ModernFixPlatformHooks.registerCreativeSearchTrees(this.searchRegistry, nameSupplier, tagSupplier, this::populateSearchTree);
// grab components for all key mappings in order to prevent them from being loaded off-thread later
// this populates the LazyLoadedValues
// we also need to suppress GLFW errors to prevent crashes if a key is missing
GLFWErrorCallback oldCb = GLFW.glfwSetErrorCallback(null);
for(KeyMapping mapping : KeyMapping.ALL.values()) {
mapping.getTranslatedKeyMessage();
}
GLFW.glfwSetErrorCallback(oldCb);
ci.cancel(); ci.cancel();
} }
} }

View File

@ -20,6 +20,8 @@ public class ModernFixMixinPlugin implements IMixinConfigPlugin {
public static ModernFixMixinPlugin instance; public static ModernFixMixinPlugin instance;
public ModernFixMixinPlugin() { public ModernFixMixinPlugin() {
/* invoke early to ensure it gets read on one thread */
ModernFixPlatformHooks.getCustomModOptions();
boolean firstConfig = instance == null; boolean firstConfig = instance == null;
if(firstConfig) { if(firstConfig) {
instance = this; instance = this;

View File

@ -183,8 +183,9 @@ public class ModernFixEarlyConfig {
disableIfModPresent("mixin.bugfix.paper_chunk_patches", "c2me"); disableIfModPresent("mixin.bugfix.paper_chunk_patches", "c2me");
disableIfModPresent("mixin.perf.reuse_datapacks", "tac"); disableIfModPresent("mixin.perf.reuse_datapacks", "tac");
disableIfModPresent("mixin.launch.class_search_cache", "optifine"); disableIfModPresent("mixin.launch.class_search_cache", "optifine");
disableIfModPresent("mixin.perf.faster_texture_stitching", "optifine");
disableIfModPresent("mixin.perf.datapack_reload_exceptions", "cyanide"); disableIfModPresent("mixin.perf.datapack_reload_exceptions", "cyanide");
disableIfModPresent("mixin.perf.faster_texture_loading", "stitch"); disableIfModPresent("mixin.perf.faster_texture_loading", "stitch", "optifine");
} }
private void disableIfModPresent(String configName, String... ids) { private void disableIfModPresent(String configName, String... ids) {

View File

@ -3,6 +3,7 @@ package org.embeddedt.modernfix.duck;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.client.resources.model.ModelState;
import net.minecraft.client.resources.model.UnbakedModel; import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
@ -11,7 +12,7 @@ import net.minecraft.world.level.block.state.StateDefinition;
public interface IExtendedModelBakery { public interface IExtendedModelBakery {
ImmutableList<BlockState> getBlockStatesForMRL(StateDefinition<Block, BlockState> stateDefinition, ModelResourceLocation location); ImmutableList<BlockState> getBlockStatesForMRL(StateDefinition<Block, BlockState> stateDefinition, ModelResourceLocation location);
BakedModel bakeDefault(ResourceLocation modelLocation); BakedModel bakeDefault(ResourceLocation modelLocation, ModelState state);
BakedModel getBakedMissingModel(); BakedModel getBakedMissingModel();
void setBakedMissingModel(BakedModel m); void setBakedMissingModel(BakedModel m);
UnbakedModel mfix$getUnbakedMissingModel(); UnbakedModel mfix$getUnbakedMissingModel();

View File

@ -15,6 +15,7 @@ import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import org.apache.commons.lang3.tuple.Triple; import org.apache.commons.lang3.tuple.Triple;
import org.embeddedt.modernfix.duck.IExtendedModelBakery; import org.embeddedt.modernfix.duck.IExtendedModelBakery;
import org.embeddedt.modernfix.ModernFix;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -109,7 +110,12 @@ public class DynamicBakedModelProvider implements Map<ResourceLocation, BakedMod
if(model != SENTINEL) if(model != SENTINEL)
return model; return model;
else { else {
model = ((IExtendedModelBakery)bakery).bakeDefault((ResourceLocation)o); try {
model = ((IExtendedModelBakery)bakery).bakeDefault((ResourceLocation)o, BlockModelRotation.X0_Y0);
} catch(RuntimeException e) {
ModernFix.LOGGER.error("Exception baking {}: {}", o, e);
model = missingModel;
}
if(model == missingModel) { if(model == missingModel) {
// to correctly emulate the original map, we return null for missing models // to correctly emulate the original map, we return null for missing models
permanentOverrides.put((ResourceLocation) o, null); permanentOverrides.put((ResourceLocation) o, null);

View File

@ -1,7 +1,8 @@
package org.embeddedt.modernfix.platform; package org.embeddedt.modernfix.platform;
import dev.architectury.injectables.annotations.ExpectPlatform; import com.google.common.collect.Multimap;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.minecraft.client.searchtree.SearchRegistry; import net.minecraft.client.searchtree.SearchRegistry;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
@ -75,6 +76,11 @@ public class ModernFixPlatformHooks {
throw new AssertionError(); throw new AssertionError();
} }
@ExpectPlatform
public static Multimap<String, String> getCustomModOptions() {
throw new AssertionError();
}
@ExpectPlatform @ExpectPlatform
public static void registerCreativeSearchTrees(SearchRegistry registry, SearchRegistry.TreeBuilderSupplier<ItemStack> nameSupplier, SearchRegistry.TreeBuilderSupplier<ItemStack> tagSupplier, BiConsumer<SearchRegistry.Key<ItemStack>, List<ItemStack>> populator) { public static void registerCreativeSearchTrees(SearchRegistry registry, SearchRegistry.TreeBuilderSupplier<ItemStack> nameSupplier, SearchRegistry.TreeBuilderSupplier<ItemStack> tagSupplier, BiConsumer<SearchRegistry.Key<ItemStack>, List<ItemStack>> populator) {
throw new AssertionError(); throw new AssertionError();

View File

@ -35,3 +35,4 @@ accessible class net/minecraft/world/level/chunk/PalettedContainer$Data
accessible field net/minecraft/server/MinecraftServer resources Lnet/minecraft/server/MinecraftServer$ReloadableResources; accessible field net/minecraft/server/MinecraftServer resources Lnet/minecraft/server/MinecraftServer$ReloadableResources;
accessible class net/minecraft/server/MinecraftServer$ReloadableResources accessible class net/minecraft/server/MinecraftServer$ReloadableResources
accessible method net/minecraft/client/gui/screens/Screen addRenderableWidget (Lnet/minecraft/client/gui/components/events/GuiEventListener;)Lnet/minecraft/client/gui/components/events/GuiEventListener; accessible method net/minecraft/client/gui/screens/Screen addRenderableWidget (Lnet/minecraft/client/gui/components/events/GuiEventListener;)Lnet/minecraft/client/gui/components/events/GuiEventListener;
accessible field net/minecraft/client/KeyMapping ALL Ljava/util/Map;

View File

@ -37,6 +37,7 @@ dependencies {
modImplementation(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } modImplementation(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modImplementation(fabricApi.module("fabric-data-generation-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } modImplementation(fabricApi.module("fabric-data-generation-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modCompileOnly("com.terraformersmc:modmenu:${rootProject.modmenu_version}") { transitive false } modCompileOnly("com.terraformersmc:modmenu:${rootProject.modmenu_version}") { transitive false }
modRuntimeOnly("net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}") { exclude group: 'net.fabricmc', module: 'fabric-loader' }
// Remove the next line if you don't want to depend on the API // Remove the next line if you don't want to depend on the API
// modApi "me.shedaniel:architectury-fabric:${rootProject.architectury_version}" // modApi "me.shedaniel:architectury-fabric:${rootProject.architectury_version}"

View File

@ -8,6 +8,8 @@ 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 org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
import org.embeddedt.modernfix.duck.IExtendedModelBakery; import org.embeddedt.modernfix.duck.IExtendedModelBakery;
import org.embeddedt.modernfix.dynamicresources.DynamicBakedModelProvider; import org.embeddedt.modernfix.dynamicresources.DynamicBakedModelProvider;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
@ -58,9 +60,18 @@ public abstract class ModelBakerImplMixin {
} }
private boolean wasMissingModel = false; private boolean wasMissingModel = false;
private ResourceLocation capturedLocation;
private UnbakedModel capturedModel;
private ModelState capturedState;
@Inject(method = "bake", at = @At("HEAD"))
private void captureState(ResourceLocation rl, ModelState state, CallbackInfoReturnable<BakedModel> cir) {
capturedState = state;
}
@Inject(method = "getModel", at = @At("HEAD"), cancellable = true) @Inject(method = "getModel", at = @At("HEAD"), cancellable = true)
private void obtainModel(ResourceLocation arg, CallbackInfoReturnable<UnbakedModel> cir) { private void obtainModel(ResourceLocation arg, CallbackInfoReturnable<UnbakedModel> cir) {
capturedLocation = arg;
if(debugDynamicModelLoading) if(debugDynamicModelLoading)
ModernFix.LOGGER.info("Baking {}", arg); ModernFix.LOGGER.info("Baking {}", arg);
IExtendedModelBakery extendedBakery = (IExtendedModelBakery)this.field_40571; IExtendedModelBakery extendedBakery = (IExtendedModelBakery)this.field_40571;
@ -91,6 +102,7 @@ public abstract class ModelBakerImplMixin {
} else } else
wasMissingModel = false; /* sometimes this runs more than once e.g. for recursive model baking */ wasMissingModel = false; /* sometimes this runs more than once e.g. for recursive model baking */
cir.getReturnValue().resolveParents(this.field_40571::getModel); cir.getReturnValue().resolveParents(this.field_40571::getModel);
capturedModel = cir.getReturnValue();
} }
@ModifyVariable(method = "bake", at = @At(value = "INVOKE_ASSIGN", 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;")) @ModifyVariable(method = "bake", at = @At(value = "INVOKE_ASSIGN", 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;"))
@ -109,6 +121,9 @@ public abstract class ModelBakerImplMixin {
} }
return missing; return missing;
} }
for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) {
model = integration.onBakedModelLoad(capturedLocation, capturedModel, model, capturedState, this.field_40571);
}
return model; return model;
} }

View File

@ -14,7 +14,9 @@ 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.ModernFix; import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
import org.embeddedt.modernfix.duck.IExtendedModelBakery; import org.embeddedt.modernfix.duck.IExtendedModelBakery;
import org.embeddedt.modernfix.dynamicresources.DynamicBakedModelProvider; import org.embeddedt.modernfix.dynamicresources.DynamicBakedModelProvider;
import org.embeddedt.modernfix.dynamicresources.ModelBakeryHelpers; import org.embeddedt.modernfix.dynamicresources.ModelBakeryHelpers;
@ -28,6 +30,7 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.*;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@ -189,6 +192,17 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
return unbakedCache.get(rl); 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;
}
/** /**
* @author embeddedt * @author embeddedt
@ -256,14 +270,14 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
} }
@Override @Override
public BakedModel bakeDefault(ResourceLocation modelLocation) { public BakedModel bakeDefault(ResourceLocation modelLocation, ModelState state) {
ModelBakery.BakedCacheKey key = new ModelBakery.BakedCacheKey(modelLocation, BlockModelRotation.X0_Y0.getRotation(), BlockModelRotation.X0_Y0.isUvLocked()); ModelBakery.BakedCacheKey key = new ModelBakery.BakedCacheKey(modelLocation, BlockModelRotation.X0_Y0.getRotation(), BlockModelRotation.X0_Y0.isUvLocked());
BakedModel m = loadedBakedModels.getIfPresent(key); BakedModel m = loadedBakedModels.getIfPresent(key);
if(m != null) if(m != null)
return m; return m;
ModelBakery self = (ModelBakery) (Object) this; ModelBakery self = (ModelBakery) (Object) this;
ModelBaker theBaker = self.new ModelBakerImpl(textureGetter, modelLocation); ModelBaker theBaker = self.new ModelBakerImpl(textureGetter, modelLocation);
m = theBaker.bake(modelLocation, BlockModelRotation.X0_Y0); m = theBaker.bake(modelLocation, state);
if(m != null) if(m != null)
loadedBakedModels.put(key, m); loadedBakedModels.put(key, m);
return m; return m;

View File

@ -1,20 +1,26 @@
package org.embeddedt.modernfix.platform.fabric; package org.embeddedt.modernfix.platform.fabric;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer; import net.fabricmc.loader.api.ModContainer;
import net.fabricmc.loader.api.metadata.CustomValue;
import net.fabricmc.loader.api.metadata.ModMetadata;
import net.minecraft.client.searchtree.SearchRegistry; import net.minecraft.client.searchtree.SearchRegistry;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
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.ItemStack; import net.minecraft.world.item.ItemStack;
import org.embeddedt.modernfix.ModernFixFabric; import org.embeddedt.modernfix.ModernFixFabric;
import org.embeddedt.modernfix.api.constants.IntegrationConstants;
import org.objectweb.asm.tree.*; import org.objectweb.asm.tree.*;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -72,6 +78,28 @@ public class ModernFixPlatformHooksImpl {
CommandRegistrationCallback.EVENT.register((dispatcher, arg, env) -> handler.accept(dispatcher)); CommandRegistrationCallback.EVENT.register((dispatcher, arg, env) -> handler.accept(dispatcher));
} }
private static Multimap<String, String> modOptions;
public static Multimap<String, String> getCustomModOptions() {
if(modOptions == null) {
modOptions = ArrayListMultimap.create();
for (ModContainer container : FabricLoader.getInstance().getAllMods()) {
ModMetadata meta = container.getMetadata();
if (meta.containsCustomValue(IntegrationConstants.INTEGRATIONS_KEY)) {
CustomValue integrations = meta.getCustomValue(IntegrationConstants.INTEGRATIONS_KEY);
if (integrations.getType() != CustomValue.CvType.OBJECT) {
continue;
}
for (Map.Entry<String, CustomValue> entry : integrations.getAsObject()) {
if(entry.getValue().getType() != CustomValue.CvType.STRING)
continue;
modOptions.put(entry.getKey(), entry.getValue().getAsString());
}
}
}
}
return modOptions;
}
public static void registerCreativeSearchTrees(SearchRegistry registry, SearchRegistry.TreeBuilderSupplier<ItemStack> nameSupplier, SearchRegistry.TreeBuilderSupplier<ItemStack> tagSupplier, BiConsumer<SearchRegistry.Key<ItemStack>, List<ItemStack>> populator) { public static void registerCreativeSearchTrees(SearchRegistry registry, SearchRegistry.TreeBuilderSupplier<ItemStack> nameSupplier, SearchRegistry.TreeBuilderSupplier<ItemStack> tagSupplier, BiConsumer<SearchRegistry.Key<ItemStack>, List<ItemStack>> populator) {
/* no-op on Fabric */ /* no-op on Fabric */
} }

View File

@ -45,7 +45,6 @@ dependencies {
modCompileOnly("team.chisel.ctm:CTM:${ctm_version}") modCompileOnly("team.chisel.ctm:CTM:${ctm_version}")
modCompileOnly("curse.maven:supermartijncore-454372:4455391") modCompileOnly("curse.maven:supermartijncore-454372:4455391")
modCompileOnly("appeng:appliedenergistics2-forge:12.9.4")
modCompileOnly("vazkii.patchouli:Patchouli:1.19.2-77") modCompileOnly("vazkii.patchouli:Patchouli:1.19.2-77")
common(project(path: ":common", configuration: "namedElements")) { transitive false } common(project(path: ":common", configuration: "namedElements")) { transitive false }

View File

@ -1,51 +0,0 @@
package org.embeddedt.modernfix.forge.dynamicresources;
import net.minecraft.client.resources.model.*;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.eventbus.api.Event;
/**
* Fired when a model is baked dynamically. Intended to be used as a replacement for ModelBakeEvent
* if mods want to replace a model.
* <p></p>
* Note that this event can fire many times for the same resource location, as models are unloaded
* if unused/under memory pressure.
*/
public class DynamicModelBakeEvent extends Event {
private final ResourceLocation location;
private BakedModel model;
private final UnbakedModel unbakedModel;
private final ModelBaker modelLoader;
private final ModelBakery modelBakery;
public DynamicModelBakeEvent(ResourceLocation location, UnbakedModel unbakedModel, BakedModel model, ModelBaker loader, ModelBakery bakery) {
this.location = location;
this.model = model;
this.unbakedModel = unbakedModel;
this.modelLoader = loader;
this.modelBakery = bakery;
}
public ResourceLocation getLocation() {
return this.location;
}
public BakedModel getModel() {
return this.model;
}
public UnbakedModel getUnbakedModel() {
return this.unbakedModel;
}
public ModelBaker getModelLoader() {
return this.modelLoader;
}
public ModelBakery getModelBakery() {
return this.modelBakery;
}
public void setModel(BakedModel model) {
this.model = model;
}
}

View File

@ -6,9 +6,10 @@ import net.minecraft.client.resources.model.*;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
import org.embeddedt.modernfix.duck.IExtendedModelBakery; import org.embeddedt.modernfix.duck.IExtendedModelBakery;
import org.embeddedt.modernfix.dynamicresources.DynamicBakedModelProvider; import org.embeddedt.modernfix.dynamicresources.DynamicBakedModelProvider;
import org.embeddedt.modernfix.forge.dynamicresources.DynamicModelBakeEvent;
import org.spongepowered.asm.mixin.Final; 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;
@ -59,10 +60,11 @@ public abstract class ModelBakerImplMixin {
} else } else
ibakedmodel = iunbakedmodel.bake((ModelBaker)this, textureGetter, arg2, arg); ibakedmodel = iunbakedmodel.bake((ModelBaker)this, textureGetter, arg2, arg);
} }
DynamicModelBakeEvent event = new DynamicModelBakeEvent(arg, iunbakedmodel, ibakedmodel, (ModelBaker)this, this.field_40571); for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) {
MinecraftForge.EVENT_BUS.post(event); ibakedmodel = integration.onBakedModelLoad(arg, iunbakedmodel, ibakedmodel, arg2, this.field_40571);
this.field_40571.bakedCache.put(key, event.getModel()); }
cir.setReturnValue(event.getModel()); this.field_40571.bakedCache.put(key, ibakedmodel);
cir.setReturnValue(ibakedmodel);
} }
} }
} }

View File

@ -14,6 +14,8 @@ 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.ModernFix; import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
import org.embeddedt.modernfix.dynamicresources.DynamicBakedModelProvider; import org.embeddedt.modernfix.dynamicresources.DynamicBakedModelProvider;
import org.embeddedt.modernfix.duck.IExtendedModelBakery; import org.embeddedt.modernfix.duck.IExtendedModelBakery;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
@ -26,6 +28,7 @@ import org.spongepowered.asm.mixin.Mutable;
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;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@ -157,6 +160,18 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
return unbakedCache.get(rl); 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")) @Inject(method = "cacheAndQueueDependencies", at = @At("RETURN"))
private void addToSmallLoadingCache(ResourceLocation location, UnbakedModel model, CallbackInfo ci) { private void addToSmallLoadingCache(ResourceLocation location, UnbakedModel model, CallbackInfo ci) {
smallLoadingCache.put(location, model); smallLoadingCache.put(location, model);
@ -229,10 +244,10 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
} }
@Override @Override
public BakedModel bakeDefault(ResourceLocation modelLocation) { public BakedModel bakeDefault(ResourceLocation modelLocation, ModelState state) {
ModelBakery self = (ModelBakery) (Object) this; ModelBakery self = (ModelBakery) (Object) this;
ModelBaker theBaker = self.new ModelBakerImpl(textureGetter, modelLocation); ModelBaker theBaker = self.new ModelBakerImpl(textureGetter, modelLocation);
return theBaker.bake(modelLocation, BlockModelRotation.X0_Y0); return theBaker.bake(modelLocation, state);
} }
@Override @Override

View File

@ -1,42 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.perf.dynamic_resources.ae2;
import appeng.core.AppEng;
import appeng.init.client.InitAutoRotatingModel;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraftforge.common.MinecraftForge;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.annotation.RequiresMod;
import org.spongepowered.asm.mixin.Final;
import org.embeddedt.modernfix.forge.dynamicresources.DynamicModelBakeEvent;
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 java.util.Map;
import java.util.function.Function;
@Mixin(InitAutoRotatingModel.class)
@RequiresMod("appliedenergistics2")
@ClientOnlyMixin
public class RegistrationMixin {
@Shadow @Final private static Map<String, Function<BakedModel, BakedModel>> CUSTOMIZERS;
@Inject(method = "init", at = @At("TAIL"), remap = false)
private static void doRegisterDynBake(CallbackInfo ci) {
MinecraftForge.EVENT_BUS.addListener(RegistrationMixin::onDynamicModelBake);
}
private static void onDynamicModelBake(DynamicModelBakeEvent event) {
if (!event.getLocation().getNamespace().equals(AppEng.MOD_ID)) {
return;
}
BakedModel missing = event.getModelBakery().getBakedTopLevelModels().get(ModelBakery.MISSING_MODEL_LOCATION);
if(event.getModel() == missing)
return;
Function<BakedModel, BakedModel> customizerFn = CUSTOMIZERS.get(event.getLocation().getPath());
if(customizerFn != null)
event.setModel(customizerFn.apply(event.getModel()));
}
}

View File

@ -3,24 +3,20 @@ package org.embeddedt.modernfix.forge.mixin.perf.dynamic_resources.ctm;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.*;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.client.resources.model.MultiPartBakedModel;
import net.minecraft.client.resources.model.WeightedBakedModel;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceLocation; 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.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.client.ChunkRenderTypeSet; import net.minecraftforge.client.ChunkRenderTypeSet;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistries;
import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.annotation.RequiresMod; import org.embeddedt.modernfix.annotation.RequiresMod;
import org.embeddedt.modernfix.duck.IExtendedModelBakery; import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
import org.embeddedt.modernfix.forge.dynamicresources.DynamicModelBakeEvent; import org.embeddedt.modernfix.api.helpers.ModelHelpers;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Overwrite;
@ -38,7 +34,7 @@ import java.util.function.Predicate;
@Mixin(CTMPackReloadListener.class) @Mixin(CTMPackReloadListener.class)
@RequiresMod("ctm") @RequiresMod("ctm")
@ClientOnlyMixin @ClientOnlyMixin
public abstract class CTMPackReloadListenerMixin { public abstract class CTMPackReloadListenerMixin implements ModernFixClientIntegration {
/* caches the original render checks */ /* caches the original render checks */
@Shadow @Final private static Map<Holder.Reference<Block>, Predicate<RenderType>> blockRenderChecks; @Shadow @Final private static Map<Holder.Reference<Block>, Predicate<RenderType>> blockRenderChecks;
@ -52,7 +48,7 @@ public abstract class CTMPackReloadListenerMixin {
@Inject(method = "<init>", at = @At("RETURN")) @Inject(method = "<init>", at = @At("RETURN"))
private void onInit(CallbackInfo ci) { private void onInit(CallbackInfo ci) {
MinecraftForge.EVENT_BUS.addListener(EventPriority.LOW, this::onModelBake); ModernFixClient.CLIENT_INTEGRATIONS.add(this);
} }
@Overwrite(remap = false) @Overwrite(remap = false)
@ -77,28 +73,32 @@ public abstract class CTMPackReloadListenerMixin {
return override.test(type); return override.test(type);
} }
private void onModelBake(DynamicModelBakeEvent event) { @Override
if(!(event.getModel() instanceof AbstractCTMBakedModel || event.getModel() instanceof WeightedBakedModel || event.getModel() instanceof MultiPartBakedModel)) public BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState modelState, ModelBakery bakery) {
return; if(!(location instanceof ModelResourceLocation))
return originalModel;
if(!(originalModel instanceof AbstractCTMBakedModel || originalModel instanceof WeightedBakedModel || originalModel instanceof MultiPartBakedModel))
return originalModel;
/* we construct a new ResourceLocation because an MRL is coming in */ /* we construct a new ResourceLocation because an MRL is coming in */
Block block = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(event.getLocation().getNamespace(), event.getLocation().getPath())); Block block = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(location.getNamespace(), location.getPath()));
Holder.Reference<Block> delegate = block != null ? ForgeRegistries.BLOCKS.getDelegateOrThrow(block) : null; Holder.Reference<Block> delegate = block != null ? ForgeRegistries.BLOCKS.getDelegateOrThrow(block) : null;
if(block == null || block == Blocks.AIR || renderCheckOverrides.containsKey(delegate)) if(block == null || block == Blocks.AIR || renderCheckOverrides.containsKey(delegate))
return; return originalModel;
/* find all states that match this MRL */ /* find all states that match this MRL */
ImmutableList<BlockState> allStates; ImmutableList<BlockState> allStates;
try { try {
allStates = ((IExtendedModelBakery)(Object)event.getModelLoader()).getBlockStatesForMRL(block.getStateDefinition(), (ModelResourceLocation)event.getLocation()); allStates = ModelHelpers.getBlockStateForLocation(block.getStateDefinition(), (ModelResourceLocation)location);
} catch(RuntimeException e) { } catch(RuntimeException e) {
ModernFix.LOGGER.error("Couldn't get state for MRL " + event.getLocation(), e); ModernFix.LOGGER.error("Couldn't get state for MRL " + location, e);
return; return originalModel;
} }
for(BlockState state : allStates) { for(BlockState state : allStates) {
Predicate<RenderType> newPredicate = this.getLayerCheck(state, event.getModel()); Predicate<RenderType> newPredicate = this.getLayerCheck(state, originalModel);
if(newPredicate != null) { if(newPredicate != null) {
renderCheckOverrides.put(delegate, newPredicate); renderCheckOverrides.put(delegate, newPredicate);
return; return originalModel;
} }
} }
return originalModel;
} }
} }

View File

@ -1,15 +1,13 @@
package org.embeddedt.modernfix.forge.mixin.perf.dynamic_resources.ctm; package org.embeddedt.modernfix.forge.mixin.perf.dynamic_resources.ctm;
import com.mojang.datafixers.util.Pair; import com.mojang.datafixers.util.Pair;
import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.*;
import net.minecraft.client.resources.model.Material;
import net.minecraft.client.resources.model.ModelBaker;
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.MinecraftForge; import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.annotation.RequiresMod; import org.embeddedt.modernfix.annotation.RequiresMod;
import org.embeddedt.modernfix.forge.dynamicresources.DynamicModelBakeEvent; import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
import org.embeddedt.modernfix.api.helpers.ModelHelpers;
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;
@ -29,13 +27,13 @@ import java.util.*;
@Mixin(TextureMetadataHandler.class) @Mixin(TextureMetadataHandler.class)
@RequiresMod("ctm") @RequiresMod("ctm")
@ClientOnlyMixin @ClientOnlyMixin
public abstract class TextureMetadataHandlerMixin { public abstract class TextureMetadataHandlerMixin implements ModernFixClientIntegration {
@Shadow @Nonnull protected abstract BakedModel wrap(ResourceLocation loc, UnbakedModel model, BakedModel object, ModelBaker loader) throws IOException; @Shadow @Nonnull protected abstract BakedModel wrap(ResourceLocation loc, UnbakedModel model, BakedModel object, ModelBaker loader) throws IOException;
@Inject(method = "<init>", at = @At("RETURN")) @Inject(method = "<init>", at = @At("RETURN"))
private void subscribeDynamic(CallbackInfo ci) { private void subscribeDynamic(CallbackInfo ci) {
MinecraftForge.EVENT_BUS.addListener(this::onDynamicModelBake); ModernFixClient.CLIENT_INTEGRATIONS.add(this);
} }
@Redirect(method = "onModelBake", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/BakedModel;isCustomRenderer()Z")) @Redirect(method = "onModelBake", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/BakedModel;isCustomRenderer()Z"))
@ -43,10 +41,8 @@ public abstract class TextureMetadataHandlerMixin {
return model == null || model.isCustomRenderer(); return model == null || model.isCustomRenderer();
} }
public void onDynamicModelBake(DynamicModelBakeEvent event) { @Override
UnbakedModel rootModel = event.getUnbakedModel(); public BakedModel onBakedModelLoad(ResourceLocation rl, UnbakedModel rootModel, BakedModel baked, ModelState state, ModelBakery bakery) {
BakedModel baked = event.getModel();
ResourceLocation rl = event.getLocation();
if (!(baked instanceof AbstractCTMBakedModel) && !baked.isCustomRenderer()) { if (!(baked instanceof AbstractCTMBakedModel) && !baked.isCustomRenderer()) {
Deque<ResourceLocation> dependencies = new ArrayDeque<>(); Deque<ResourceLocation> dependencies = new ArrayDeque<>();
Set<ResourceLocation> seenModels = new HashSet<>(); Set<ResourceLocation> seenModels = new HashSet<>();
@ -59,7 +55,7 @@ public abstract class TextureMetadataHandlerMixin {
ResourceLocation dep = dependencies.pop(); ResourceLocation dep = dependencies.pop();
UnbakedModel model; UnbakedModel model;
try { try {
model = dep == rl ? rootModel : event.getModelLoader().getModel(dep); model = dep == rl ? rootModel : bakery.getModel(dep);
} catch (Exception e) { } catch (Exception e) {
continue; continue;
} }
@ -87,12 +83,13 @@ public abstract class TextureMetadataHandlerMixin {
} }
if (shouldWrap) { if (shouldWrap) {
try { try {
event.setModel(wrap(rl, rootModel, baked, event.getModelLoader())); baked = wrap(rl, rootModel, baked, ModelHelpers.adaptBakery(bakery));
dependencies.clear(); dependencies.clear();
} catch (IOException e) { } catch (IOException e) {
CTM.logger.error("Could not wrap model " + rl + ". Aborting...", e); CTM.logger.error("Could not wrap model " + rl + ". Aborting...", e);
} }
} }
} }
return baked;
} }
} }

View File

@ -2,12 +2,12 @@ package org.embeddedt.modernfix.forge.mixin.perf.dynamic_resources.rs;
import com.refinedmods.refinedstorage.render.BakedModelOverrideRegistry; import com.refinedmods.refinedstorage.render.BakedModelOverrideRegistry;
import com.refinedmods.refinedstorage.setup.ClientSetup; import com.refinedmods.refinedstorage.setup.ClientSetup;
import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.client.resources.model.*;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.MinecraftForge; import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.annotation.RequiresMod; import org.embeddedt.modernfix.annotation.RequiresMod;
import org.embeddedt.modernfix.forge.dynamicresources.DynamicModelBakeEvent; import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
import org.spongepowered.asm.mixin.Final; 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;
@ -15,20 +15,24 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ClientSetup.class) @Mixin(ClientSetup.class)
@RequiresMod("refinedstorage") @RequiresMod("refinedstorage")
@ClientOnlyMixin @ClientOnlyMixin
public class ClientSetupMixin { public class ClientSetupMixin {
@Shadow @Final private static BakedModelOverrideRegistry BAKED_MODEL_OVERRIDE_REGISTRY; @Shadow @Final private static BakedModelOverrideRegistry BAKED_MODEL_OVERRIDE_REGISTRY;
@Inject(method = "onClientSetup", at = @At("RETURN"), remap = false) @Inject(method = "<init>", at = @At("RETURN"))
private static void addDynamicListener(CallbackInfo ci) { private void addDynamicListener(CallbackInfo ci) {
MinecraftForge.EVENT_BUS.addListener(ClientSetupMixin::onDynamicModelBake); ModernFixClient.CLIENT_INTEGRATIONS.add(new ModernFixClientIntegration() {
} @Override
public BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery) {
private static void onDynamicModelBake(DynamicModelBakeEvent event) { BakedModelOverrideRegistry.BakedModelOverrideFactory factory = BAKED_MODEL_OVERRIDE_REGISTRY.get(location instanceof ModelResourceLocation ? new ResourceLocation(location.getNamespace(), location.getPath()) : location);
BakedModelOverrideRegistry.BakedModelOverrideFactory factory = BAKED_MODEL_OVERRIDE_REGISTRY.get(event.getLocation() instanceof ModelResourceLocation ? new ResourceLocation(event.getLocation().getNamespace(), event.getLocation().getPath()) : event.getLocation()); if(factory != null)
if(factory != null) return factory.create(originalModel, bakery.getBakedTopLevelModels());
event.setModel(factory.create(event.getModel(), event.getModelBakery().getBakedTopLevelModels())); else
return originalModel;
}
});
} }
} }

View File

@ -4,12 +4,14 @@ import com.supermartijn642.core.registry.ClientRegistrationHandler;
import com.supermartijn642.core.util.Pair; import com.supermartijn642.core.util.Pair;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.client.resources.model.BakedModel; 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 net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.MinecraftForge; import org.embeddedt.modernfix.ModernFixClient;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.annotation.RequiresMod; import org.embeddedt.modernfix.annotation.RequiresMod;
import org.embeddedt.modernfix.forge.dynamicresources.DynamicModelBakeEvent; import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
import org.spongepowered.asm.mixin.Final; 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;
@ -48,13 +50,15 @@ public class ClientRegistrationHandlerMixin {
@Inject(method = "<init>", at = @At("RETURN")) @Inject(method = "<init>", at = @At("RETURN"))
private void registerDynBake(String modid, CallbackInfo ci) { private void registerDynBake(String modid, CallbackInfo ci) {
MinecraftForge.EVENT_BUS.addListener(this::onDynamicModelBake); ModernFixClient.CLIENT_INTEGRATIONS.add(new ModernFixClientIntegration() {
} @Override
public BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery) {
@SubscribeEvent Function<BakedModel, BakedModel> replacer = modelOverwritesByLocation.get(location);
public void onDynamicModelBake(DynamicModelBakeEvent event) { if(replacer != null)
Function<BakedModel, BakedModel> replacer = modelOverwritesByLocation.get(event.getLocation()); return replacer.apply(originalModel);
if(replacer != null) else
event.setModel(replacer.apply(event.getModel())); return originalModel;
}
});
} }
} }

View File

@ -1,5 +1,7 @@
package org.embeddedt.modernfix.platform.forge; package org.embeddedt.modernfix.platform.forge;
import com.google.common.collect.ArrayListMultimap;
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.client.searchtree.SearchRegistry;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
@ -18,7 +20,9 @@ import net.minecraftforge.fml.loading.LoadingModList;
import net.minecraftforge.fml.loading.moddiscovery.ExplodedDirectoryLocator; import net.minecraftforge.fml.loading.moddiscovery.ExplodedDirectoryLocator;
import net.minecraftforge.network.PacketDistributor; import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.server.ServerLifecycleHooks; import net.minecraftforge.server.ServerLifecycleHooks;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
import org.embeddedt.modernfix.core.ModernFixMixinPlugin; import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
import org.embeddedt.modernfix.api.constants.IntegrationConstants;
import org.embeddedt.modernfix.forge.classloading.FastAccessTransformerList; import org.embeddedt.modernfix.forge.classloading.FastAccessTransformerList;
import org.embeddedt.modernfix.forge.packet.PacketHandler; import org.embeddedt.modernfix.forge.packet.PacketHandler;
import org.embeddedt.modernfix.util.DummyList; import org.embeddedt.modernfix.util.DummyList;
@ -100,11 +104,31 @@ public class ModernFixPlatformHooksImpl {
}); });
} }
private static Multimap<String, String> modOptions;
public static Multimap<String, String> getCustomModOptions() {
if(modOptions == null) {
modOptions = ArrayListMultimap.create();
for (ModInfo meta : LoadingModList.get().getMods()) {
meta.getConfigElement(IntegrationConstants.INTEGRATIONS_KEY).ifPresent(optionsObj -> {
if(optionsObj instanceof Map) {
Map<Object, Object> options = (Map<Object, Object>)optionsObj;
options.forEach((key, value) -> {
if(key instanceof String && value instanceof String) {
modOptions.put((String)key, (String)value);
}
});
}
});
}
}
return modOptions;
}
public static void registerCreativeSearchTrees(SearchRegistry registry, SearchRegistry.TreeBuilderSupplier<ItemStack> nameSupplier, SearchRegistry.TreeBuilderSupplier<ItemStack> tagSupplier, BiConsumer<SearchRegistry.Key<ItemStack>, List<ItemStack>> populator) { public static 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()) { for (SearchRegistry.Key<ItemStack> nameKey : CreativeModeTabSearchRegistry.getNameSearchKeys().values()) {
registry.register(nameKey, nameSupplier); registry.register(nameKey, nameSupplier);
} }
for(SearchRegistry.Key<ItemStack> tagKey : CreativeModeTabSearchRegistry.getTagSearchKeys().values()) { for (SearchRegistry.Key<ItemStack> tagKey : CreativeModeTabSearchRegistry.getTagSearchKeys().values()) {
registry.register(tagKey, tagSupplier); registry.register(tagKey, tagSupplier);
} }
Map<CreativeModeTab, SearchRegistry.Key<ItemStack>> tagSearchKeys = CreativeModeTabSearchRegistry.getTagSearchKeys(); Map<CreativeModeTab, SearchRegistry.Key<ItemStack>> tagSearchKeys = CreativeModeTabSearchRegistry.getTagSearchKeys();

View File

@ -13,7 +13,7 @@ ctm_version=1.19.2-1.1.7+11
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
fabric_loader_version=0.14.18 fabric_loader_version=0.14.19
fabric_api_version=0.80.0+1.19.4 fabric_api_version=0.80.0+1.19.4
continuity_version=3.0.0-beta.2+1.19.3 continuity_version=3.0.0-beta.2+1.19.3