Update to 1.21.3, fix tests
This commit is contained in:
parent
e0d24d4cdb
commit
f374bcbb3a
|
|
@ -1,7 +1,7 @@
|
||||||
package org.embeddedt.modernfix.fabric.mixin.core;
|
package org.embeddedt.modernfix.common.mixin.core;
|
||||||
|
|
||||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
import org.embeddedt.modernfix.ModernFixClientFabric;
|
import org.embeddedt.modernfix.ModernFixClient;
|
||||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
|
@ -13,6 +13,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
public class ClientPlayNetHandlerMixin {
|
public class ClientPlayNetHandlerMixin {
|
||||||
@Inject(method = "handleUpdateRecipes", at = @At("RETURN"))
|
@Inject(method = "handleUpdateRecipes", at = @At("RETURN"))
|
||||||
private void signalRecipes(CallbackInfo ci) {
|
private void signalRecipes(CallbackInfo ci) {
|
||||||
ModernFixClientFabric.commonMod.onRecipesUpdated();
|
ModernFixClient.INSTANCE.onRecipesUpdated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
package net.minecraft.world.level.block.state;
|
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.world.level.EmptyBlockGetter;
|
|
||||||
import net.minecraft.world.level.block.Block;
|
|
||||||
import net.minecraft.world.level.block.Blocks;
|
|
||||||
import org.embeddedt.modernfix.duck.IBlockState;
|
|
||||||
import org.embeddedt.modernfix.testing.util.BootstrapMinecraft;
|
|
||||||
import org.junit.jupiter.api.*;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
@BootstrapMinecraft
|
|
||||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
|
||||||
public class BlockStateCacheTest {
|
|
||||||
@BeforeEach
|
|
||||||
public void rebuildCache() {
|
|
||||||
Blocks.rebuildCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initially, the cache should be invalid, and null.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
@Order(1)
|
|
||||||
public void testCacheNullInitially() {
|
|
||||||
BlockState stoneBlock = Blocks.STONE.defaultBlockState();
|
|
||||||
assertTrue(((IBlockState)stoneBlock).isCacheInvalid());
|
|
||||||
assertNull(stoneBlock.cache);
|
|
||||||
|
|
||||||
// make sure lazy cache correctly handles solid
|
|
||||||
assertTrue(stoneBlock.isSolid());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When an API that needs the cache is called, it should be built and the invalid flag
|
|
||||||
* becomes false.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
@Order(2)
|
|
||||||
public void testCacheBuiltByRequest() {
|
|
||||||
BlockState stoneBlock = Blocks.STONE.defaultBlockState();
|
|
||||||
stoneBlock.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
|
|
||||||
assertFalse(((IBlockState)stoneBlock).isCacheInvalid());
|
|
||||||
assertNotNull(stoneBlock.cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When a second rebuild occurs, the invalid flag should be set to true, but the old cache
|
|
||||||
* is not set to null, in order to prevent NPEs if a second thread is accessing the cache
|
|
||||||
* when this takes place.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
@Order(3)
|
|
||||||
public void testCacheInvalidatedByLateRebuild() {
|
|
||||||
BlockState stoneBlock = Blocks.STONE.defaultBlockState();
|
|
||||||
stoneBlock.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
|
|
||||||
Blocks.rebuildCache();
|
|
||||||
assertTrue(((IBlockState)stoneBlock).isCacheInvalid());
|
|
||||||
assertNotNull(stoneBlock.cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that the fluidState and isRandomlyTicking caching fields added by Mojang to blockstates are correctly
|
|
||||||
* handled by the dynamic cache system.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
@Order(4)
|
|
||||||
public void testExtraFieldCachingCorrect() {
|
|
||||||
Block[] blocksToCheck = new Block[] { Blocks.WATER, Blocks.FARMLAND };
|
|
||||||
for(Block block : blocksToCheck) {
|
|
||||||
for(BlockState state : block.getStateDefinition().getPossibleStates()) {
|
|
||||||
// check that the fluid states match
|
|
||||||
assertEquals(block.getFluidState(state), state.getFluidState(), "mismatched fluid state on " + state);
|
|
||||||
// check that random ticking flag matches
|
|
||||||
assertEquals(block.isRandomlyTicking(state), state.isRandomlyTicking(), "mismatched random tick state on " + state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
@Test
|
|
||||||
@Order(5)
|
|
||||||
public void checkRecursiveFluidState() {
|
|
||||||
Block b = new Block(BlockBehaviour.Properties.copy(Blocks.STONE)) {
|
|
||||||
@Override
|
|
||||||
public FluidState getFluidState(BlockState state) {
|
|
||||||
return state.getFluidState();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
BlockState state = b.getStateDefinition().any();
|
|
||||||
((IBlockState)state).clearCache();
|
|
||||||
// this should not throw
|
|
||||||
state.getFluidState();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
@ -19,7 +19,7 @@ public class DynamicModelCacheTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCacheFunctions() {
|
public void testCacheFunctions() {
|
||||||
BakedModel model = new BuiltInModel(null, null, null, false);
|
BakedModel model = new BuiltInModel(null, null, false);
|
||||||
DynamicModelCache<Item> cache = new DynamicModelCache(k -> model, true);
|
DynamicModelCache<Item> cache = new DynamicModelCache(k -> model, true);
|
||||||
assertEquals(model, cache.get(Items.STONE));
|
assertEquals(model, cache.get(Items.STONE));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ 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.2-rc1
|
minecraft_version=1.21.3
|
||||||
enabled_platforms=fabric
|
enabled_platforms=fabric,neoforge
|
||||||
forge_version=21.1.15
|
forge_version=21.3.1-beta
|
||||||
parchment_version=2024.07.07
|
parchment_version=2024.07.07
|
||||||
parchment_mc_version=1.21
|
parchment_mc_version=1.21
|
||||||
refined_storage_version=4392788
|
refined_storage_version=4392788
|
||||||
|
|
@ -18,8 +18,8 @@ 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.1
|
supported_minecraft_versions=1.21.1
|
||||||
|
|
||||||
fabric_loader_version=0.16.6
|
fabric_loader_version=0.16.7
|
||||||
fabric_api_version=0.106.0+1.21.2
|
fabric_api_version=0.106.1+1.21.3
|
||||||
|
|
||||||
continuity_version=3.0.0-beta.4+1.20.2
|
continuity_version=3.0.0-beta.4+1.20.2
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import com.google.common.graph.GraphBuilder;
|
||||||
import com.google.common.graph.MutableGraph;
|
import com.google.common.graph.MutableGraph;
|
||||||
import net.minecraft.client.renderer.block.BlockModelShaper;
|
import net.minecraft.client.renderer.block.BlockModelShaper;
|
||||||
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.MissingBlockModel;
|
||||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||||
import net.minecraft.core.registries.BuiltInRegistries;
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
@ -125,7 +125,7 @@ public class ModelBakeEventHelper {
|
||||||
if(modIdsToInclude.stream().noneMatch(INCOMPATIBLE_MODS::contains))
|
if(modIdsToInclude.stream().noneMatch(INCOMPATIBLE_MODS::contains))
|
||||||
return createWarningRegistry(modId);
|
return createWarningRegistry(modId);
|
||||||
Set<ModelResourceLocation> ourModelLocations = Sets.filter(this.topLevelModelLocations, loc -> modIdsToInclude.contains(loc.id().getNamespace()));
|
Set<ModelResourceLocation> ourModelLocations = Sets.filter(this.topLevelModelLocations, loc -> modIdsToInclude.contains(loc.id().getNamespace()));
|
||||||
BakedModel missingModel = modelRegistry.get(ModelBakery.MISSING_MODEL_VARIANT);
|
BakedModel missingModel = modelRegistry.get(MissingBlockModel.VARIANT);
|
||||||
return new ForwardingMap<ModelResourceLocation, BakedModel>() {
|
return new ForwardingMap<ModelResourceLocation, BakedModel>() {
|
||||||
@Override
|
@Override
|
||||||
protected Map<ModelResourceLocation, BakedModel> delegate() {
|
protected Map<ModelResourceLocation, BakedModel> delegate() {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ import net.neoforged.fml.ModLoadingIssue;
|
||||||
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
|
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
|
||||||
import net.neoforged.neoforge.client.event.ClientTickEvent;
|
import net.neoforged.neoforge.client.event.ClientTickEvent;
|
||||||
import net.neoforged.neoforge.client.event.CustomizeGuiOverlayEvent;
|
import net.neoforged.neoforge.client.event.CustomizeGuiOverlayEvent;
|
||||||
import net.neoforged.neoforge.client.event.RecipesUpdatedEvent;
|
|
||||||
import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent;
|
import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent;
|
||||||
import net.neoforged.neoforge.client.event.RenderFrameEvent;
|
import net.neoforged.neoforge.client.event.RenderFrameEvent;
|
||||||
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
|
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
|
||||||
|
|
@ -87,7 +86,7 @@ public class ModernFixClientForge {
|
||||||
public void onDisconnect(LevelEvent.Unload event) {
|
public void onDisconnect(LevelEvent.Unload event) {
|
||||||
if(event.getLevel().isClientSide()) {
|
if(event.getLevel().isClientSide()) {
|
||||||
DebugScreenOverlay overlay = Minecraft.getInstance().getDebugOverlay();
|
DebugScreenOverlay overlay = Minecraft.getInstance().getDebugOverlay();
|
||||||
Minecraft.getInstance().tell(overlay::clearChunkCache);
|
Minecraft.getInstance().execute(overlay::clearChunkCache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,11 +100,6 @@ public class ModernFixClientForge {
|
||||||
commonMod.onRenderTickEnd();
|
commonMod.onRenderTickEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
|
||||||
public void onRecipes(RecipesUpdatedEvent e) {
|
|
||||||
commonMod.onRecipesUpdated();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||||
public void onTags(TagsUpdatedEvent e) {
|
public void onTags(TagsUpdatedEvent e) {
|
||||||
commonMod.onTagsUpdated();
|
commonMod.onTagsUpdated();
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
@Mixin(LivingEntityRenderer.class)
|
@Mixin(LivingEntityRenderer.class)
|
||||||
@ClientOnlyMixin
|
@ClientOnlyMixin
|
||||||
public class LivingEntityRendererMixin {
|
public class LivingEntityRendererMixin {
|
||||||
@Redirect(method = "render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "INVOKE", target = "Lnet/neoforged/bus/api/IEventBus;post(Lnet/neoforged/bus/api/Event;)Lnet/neoforged/bus/api/Event;", ordinal = 0))
|
@Redirect(method = "render(Lnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "INVOKE", target = "Lnet/neoforged/bus/api/IEventBus;post(Lnet/neoforged/bus/api/Event;)Lnet/neoforged/bus/api/Event;", ordinal = 0))
|
||||||
private Event fireCheckingPoseStack(IEventBus instance, Event event) {
|
private Event fireCheckingPoseStack(IEventBus instance, Event event) {
|
||||||
PoseStack stack = ((RenderLivingEvent)event).getPoseStack();
|
PoseStack stack = ((RenderLivingEvent)event).getPoseStack();
|
||||||
int size = ((PoseStackAccessor)stack).getPoseStack().size();
|
int size = ((PoseStackAccessor)stack).getPoseStack().size();
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
@Mixin(PlayerRenderer.class)
|
@Mixin(PlayerRenderer.class)
|
||||||
@ClientOnlyMixin
|
@ClientOnlyMixin
|
||||||
public class PlayerRendererMixin {
|
public class PlayerRendererMixin {
|
||||||
@Redirect(method = "render(Lnet/minecraft/client/player/AbstractClientPlayer;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "INVOKE", target = "Lnet/neoforged/bus/api/IEventBus;post(Lnet/neoforged/bus/api/Event;)Lnet/neoforged/bus/api/Event;", ordinal = 0))
|
@Redirect(method = "render(Lnet/minecraft/client/renderer/entity/state/PlayerRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "INVOKE", target = "Lnet/neoforged/bus/api/IEventBus;post(Lnet/neoforged/bus/api/Event;)Lnet/neoforged/bus/api/Event;", ordinal = 0), remap = false)
|
||||||
private Event fireCheckingPoseStack(IEventBus instance, Event event) {
|
private Event fireCheckingPoseStack(IEventBus instance, Event event) {
|
||||||
PoseStack stack = ((RenderPlayerEvent)event).getPoseStack();
|
PoseStack stack = ((RenderPlayerEvent)event).getPoseStack();
|
||||||
int size = ((PoseStackAccessor)stack).getPoseStack().size();
|
int size = ((PoseStackAccessor)stack).getPoseStack().size();
|
||||||
|
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
package org.embeddedt.modernfix.neoforge.mixin.perf.datapack_reload_exceptions;
|
|
||||||
|
|
||||||
import net.minecraft.world.item.crafting.RecipeManager;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
|
||||||
|
|
||||||
@Mixin(value = RecipeManager.class, priority = 2000)
|
|
||||||
public class RecipeManagerMixin {
|
|
||||||
@Redirect(method = "apply(Ljava/util/Map;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;error(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V", remap = false), require = 0)
|
|
||||||
private void silenceException(Logger instance, String s, Object location, Object exc) {
|
|
||||||
instance.error(s + ": {}", location, exc.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
package org.embeddedt.modernfix.neoforge.mixin.perf.dynamic_resources;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.ItemModelShaper;
|
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
|
||||||
import net.minecraft.client.resources.model.ModelManager;
|
|
||||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.item.Item;
|
|
||||||
import net.neoforged.neoforge.client.model.RegistryAwareItemModelShaper;
|
|
||||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
|
||||||
import org.embeddedt.modernfix.dynamicresources.DynamicModelCache;
|
|
||||||
import org.embeddedt.modernfix.dynamicresources.ModelLocationCache;
|
|
||||||
import org.embeddedt.modernfix.util.ItemMesherMap;
|
|
||||||
import org.spongepowered.asm.mixin.*;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Mixin(RegistryAwareItemModelShaper.class)
|
|
||||||
@ClientOnlyMixin
|
|
||||||
public abstract class ItemModelMesherForgeMixin extends ItemModelShaper {
|
|
||||||
@Shadow(remap = false) @Final @Mutable private Map<Item, ModelResourceLocation> locations;
|
|
||||||
|
|
||||||
private Map<Item, ModelResourceLocation> overrideLocations;
|
|
||||||
|
|
||||||
private final DynamicModelCache<Item> mfix$modelCache = new DynamicModelCache<>(k -> this.mfix$getModelSlow((Item)k), true);
|
|
||||||
|
|
||||||
public ItemModelMesherForgeMixin(ModelManager arg) {
|
|
||||||
super(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final ModelResourceLocation SENTINEL = new ModelResourceLocation(ResourceLocation.fromNamespaceAndPath("modernfix", "sentinel"), "sentinel");
|
|
||||||
|
|
||||||
@Inject(method = "<init>", at = @At("RETURN"))
|
|
||||||
private void replaceLocationMap(CallbackInfo ci) {
|
|
||||||
overrideLocations = new HashMap<>();
|
|
||||||
// need to replace this map because mods query locations through it
|
|
||||||
locations = new ItemMesherMap<>(this::mfix$getLocationForge);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Unique
|
|
||||||
private ModelResourceLocation mfix$getLocationForge(Item item) {
|
|
||||||
ModelResourceLocation map = overrideLocations.getOrDefault(item, SENTINEL);
|
|
||||||
if(map == SENTINEL) {
|
|
||||||
/* generate the appropriate location from our cache */
|
|
||||||
map = ModelLocationCache.get(item);
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
private BakedModel mfix$getModelSlow(Item key) {
|
|
||||||
ModelResourceLocation map = mfix$getLocationForge(key);
|
|
||||||
return map == null ? null : getModelManager().getModel(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author embeddedt
|
|
||||||
* @reason Get the stored location for that item and meta, and get the model
|
|
||||||
* from that location from the model manager.
|
|
||||||
**/
|
|
||||||
@Overwrite
|
|
||||||
@Override
|
|
||||||
public BakedModel getItemModel(Item item) {
|
|
||||||
return this.mfix$modelCache.get(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author embeddedt
|
|
||||||
* @reason Don't get all models during init (with dynamic loading, that would
|
|
||||||
* generate them all). Just store location instead.
|
|
||||||
**/
|
|
||||||
@Overwrite
|
|
||||||
@Override
|
|
||||||
public void register(Item item, ModelResourceLocation location) {
|
|
||||||
overrideLocations.put(item, location);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author embeddedt
|
|
||||||
* @reason Disable cache rebuilding (with dynamic loading, that would generate
|
|
||||||
* all models).
|
|
||||||
**/
|
|
||||||
@Overwrite
|
|
||||||
@Override
|
|
||||||
public void rebuildCache() {
|
|
||||||
this.mfix$modelCache.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
package org.embeddedt.modernfix.neoforge.mixin.perf.dynamic_resources;
|
|
||||||
|
|
||||||
import net.minecraft.client.resources.model.ModelBakery;
|
|
||||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
|
||||||
import net.minecraft.client.resources.model.UnbakedModel;
|
|
||||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
|
||||||
import org.embeddedt.modernfix.duck.IExtendedModelBakery;
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.Overwrite;
|
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
|
||||||
|
|
||||||
@Mixin(targets = {"net/minecraft/client/resources/model/ModelBakery$ModelBakerImpl"})
|
|
||||||
@ClientOnlyMixin
|
|
||||||
public class ModelBakerImplMixin {
|
|
||||||
@Shadow @Final private ModelBakery field_40571;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author embeddedt
|
|
||||||
* @reason Handle dynamic model loading
|
|
||||||
*/
|
|
||||||
@Overwrite(remap = false)
|
|
||||||
public UnbakedModel getTopLevelModel(ModelResourceLocation location) {
|
|
||||||
IExtendedModelBakery bakery = (IExtendedModelBakery)this.field_40571;
|
|
||||||
UnbakedModel model = bakery.mfix$loadUnbakedModelDynamic(location);
|
|
||||||
return model == bakery.mfix$getMissingModel() ? null : model;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
package org.embeddedt.modernfix.neoforge.mixin.perf.dynamic_resources.ctm;
|
|
||||||
|
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
|
||||||
import net.minecraft.client.resources.model.ModelBakery;
|
|
||||||
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Mixin(ModelBakery.class)
|
|
||||||
@ClientOnlyMixin
|
|
||||||
public interface CTMModelBakeryAccessor {
|
|
||||||
@Accessor("bakedCache")
|
|
||||||
Map<ModelBakery.BakedCacheKey, BakedModel> mfix$getBakedCache();
|
|
||||||
}
|
|
||||||
|
|
@ -1,114 +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.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;
|
|
||||||
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.*;
|
|
||||||
|
|
||||||
@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(remap = false) @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$BakingCompleted;)V", "onModelBake(Lnet/neoforged/neoforge/client/event/ModelEvent$ModifyBakingResult;)V" }, at = @At("HEAD"), cancellable = true, remap = false)
|
|
||||||
private void noIteration(CallbackInfo ci) {
|
|
||||||
ci.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BakedModel onBakedModelLoad(ModelResourceLocation mrl, UnbakedModel rootModel, BakedModel baked, ModelState state, ModelBakery bakery, ModelBakery.TextureGetter getter) {
|
|
||||||
if (!(baked instanceof AbstractCTMBakedModel) && !baked.isCustomRenderer()) {
|
|
||||||
Deque<ResourceLocation> dependencies = new ArrayDeque<>();
|
|
||||||
Set<ResourceLocation> seenModels = new HashSet<>();
|
|
||||||
dependencies.push(mrl.id());
|
|
||||||
seenModels.add(mrl.id());
|
|
||||||
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 == mrl.id() ? 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(mrl, baked, bakery, getter);
|
|
||||||
dependencies.clear();
|
|
||||||
} catch (IOException e) {
|
|
||||||
CTM.logger.error("Could not wrap model " + mrl + ". Aborting...", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return baked;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleInit(ModelResourceLocation key, BakedModel wrappedModel, ModelBakery bakery, ModelBakery.TextureGetter spriteGetter) {
|
|
||||||
if(wrappedModel instanceof AbstractCTMBakedModel baked) {
|
|
||||||
IModelCTM var10 = baked.getModel();
|
|
||||||
if (var10 instanceof ModelCTM ctmModel) {
|
|
||||||
if (!ctmModel.isInitialized()) {
|
|
||||||
// Clear the baked cache as upstream CTM does
|
|
||||||
((CTMModelBakeryAccessor)bakery).mfix$getBakedCache().clear();
|
|
||||||
ModelBakery.ModelBakerImpl baker = bakery.new ModelBakerImpl(spriteGetter, key);
|
|
||||||
ctmModel.bake(baker, Material::sprite, BlockModelRotation.X0_Y0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
package org.embeddedt.modernfix.neoforge.mixin.perf.reduce_blockstate_cache_rebuilds;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import net.minecraft.core.Registry;
|
|
||||||
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.blockstate.BlockStateCacheHandler;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
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;
|
|
||||||
|
|
||||||
@Mixin(targets = { "net/neoforged/neoforge/registries/NeoForgeRegistryCallbacks$BlockCallbacks" })
|
|
||||||
public class BlockCallbacksMixin {
|
|
||||||
@Redirect(method = "onBake", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/StateDefinition;getPossibleStates()Lcom/google/common/collect/ImmutableList;", ordinal = 0))
|
|
||||||
private ImmutableList<BlockState> skipCache(StateDefinition<Block, BlockState> definition) {
|
|
||||||
// prevent initCache from being called on these blockstates
|
|
||||||
return ImmutableList.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject(method = "onBake", at = @At(value = "TAIL"), remap = false)
|
|
||||||
private void computeCaches(Registry<Block> registry, CallbackInfo ci) {
|
|
||||||
BlockStateCacheHandler.rebuildParallel(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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 = "[21.0.111-beta,)" #mandatory
|
versionRange = "[21.3.1-beta,)" #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.21, 1.22)"
|
versionRange = "[1.21.3, 1.22)"
|
||||||
ordering = "NONE"
|
ordering = "NONE"
|
||||||
side = "BOTH"
|
side = "BOTH"
|
||||||
[[dependencies.modernfix]]
|
[[dependencies.modernfix]]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user