diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 00000000..aa708afc --- /dev/null +++ b/TODO.txt @@ -0,0 +1,7 @@ +- Reimplement mixin.bugfix.entity_pose_stack +- Reimplement dynamic_resources +- Investigate if cache_strongholds is still needed in 26.1 +- Check if BlockStateData patch is still needed in compact_mojang_registries +- Check if faster_texture_stitching is still worthwhile with 21.x changes to the stitcher +- Sculk deadlock fix looks unnecessary since Mojang is careful about when they send the event +- Rewrite deduplicate_wall_shapes diff --git a/build.gradle.kts b/build.gradle.kts index 7dd6fedc..a40a0591 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -61,6 +61,9 @@ neoForge { } runs { + configureEach { + systemProperty("modernfix.auditMixinsAtStart", "true") + } create("client") { client() } @@ -133,7 +136,6 @@ val embed by configurations.creating { dependencies { implementation(project(":annotations")) embed(project(":annotations")) - "additionalRuntimeClasspath"(project(":annotations")) annotationProcessor(project(path = ":annotation-processor", configuration = "shadow")) val jei_version = rootProject.properties["jei_version"].toString() @@ -142,7 +144,6 @@ dependencies { compileOnly("curse.maven:ctm-267602:${rootProject.properties["ctm_version"].toString()}") compileOnly("curse.maven:ldlib-626676:${rootProject.properties["ldlib_version"].toString()}") compileOnly("curse.maven:supermartijncore-454372:4455391") - compileOnly("curse.maven:patchouli-306770:6164575") compileOnly("curse.maven:cofhcore-69162:5374122") compileOnly("curse.maven:resourcefullib-570073:5659871") compileOnly("curse.maven:kubejs-238086:5853326") @@ -162,6 +163,8 @@ tasks.withType().configureEach { ) ) } + // Show more errors when porting + options.compilerArgs.addAll(listOf("-Xmaxerrs", "1000")) } sourceSets { diff --git a/gradle.properties b/gradle.properties index 19b9d054..6f06cdda 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,13 +5,13 @@ junit_version=5.10.0-M1 mixinextras_version=0.4.1 mod_id=modernfix -minecraft_version=1.21.1 +minecraft_version=1.21.11 enabled_platforms=neoforge -forge_version=21.1.111 -parchment_version=2024.11.17 -parchment_mc_version=1.21.1 +forge_version=21.11.14-beta +parchment_version=2025.12.20 +parchment_mc_version=1.21.11 refined_storage_version=4392788 -jei_version=19.21.2.313 +jei_version=27.3.0.12 rei_version=13.0.678 ctm_version=5587515 ldlib_version=5782845 diff --git a/src/main/java/org/embeddedt/modernfix/ModernFix.java b/src/main/java/org/embeddedt/modernfix/ModernFix.java index 17e27d64..09deaaa9 100644 --- a/src/main/java/org/embeddedt/modernfix/ModernFix.java +++ b/src/main/java/org/embeddedt/modernfix/ModernFix.java @@ -1,7 +1,8 @@ package org.embeddedt.modernfix; import net.minecraft.SharedConstants; -import net.minecraft.Util; +import net.minecraft.TracingExecutor; +import net.minecraft.util.Util; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; @@ -14,7 +15,6 @@ import org.embeddedt.modernfix.resources.ReloadExecutor; import org.embeddedt.modernfix.util.ClassInfoManager; import java.lang.management.ManagementFactory; -import java.util.concurrent.ExecutorService; // The value here should match an entry in the META-INF/mods.toml file public class ModernFix { @@ -31,24 +31,24 @@ public class ModernFix { // Used to skip computing the blockstate caches twice public static boolean runningFirstInjection = false; - private static ExecutorService resourceReloadService = null; + private static TracingExecutor resourceReloadService = null; static { if(ModernFixMixinPlugin.instance.isOptionEnabled("perf.dedicated_reload_executor.ReloadExecutor")) { - resourceReloadService = ReloadExecutor.createCustomResourceReloadExecutor(); + resourceReloadService = new TracingExecutor(ReloadExecutor.createCustomResourceReloadExecutor()); } else { resourceReloadService = Util.backgroundExecutor(); } } - public static ExecutorService resourceReloadExecutor() { + public static TracingExecutor resourceReloadExecutor() { return resourceReloadService; } public ModernFix() { INSTANCE = this; - if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.snapshot_easter_egg.NameChange") && !SharedConstants.getCurrentVersion().isStable()) + if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.snapshot_easter_egg.NameChange") && !SharedConstants.getCurrentVersion().stable()) NAME = "PreemptiveFix"; ModernFixPlatformHooks.INSTANCE.onServerCommandRegister(ModernFixCommands::register); } diff --git a/src/main/java/org/embeddedt/modernfix/api/entrypoint/ModernFixClientIntegration.java b/src/main/java/org/embeddedt/modernfix/api/entrypoint/ModernFixClientIntegration.java index d6310537..3d49ff1c 100644 --- a/src/main/java/org/embeddedt/modernfix/api/entrypoint/ModernFixClientIntegration.java +++ b/src/main/java/org/embeddedt/modernfix/api/entrypoint/ModernFixClientIntegration.java @@ -1,11 +1,5 @@ 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.ModelResourceLocation; -import net.minecraft.client.resources.model.ModelState; -import net.minecraft.client.resources.model.UnbakedModel; - /** * 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. @@ -19,19 +13,4 @@ public interface ModernFixClientIntegration { */ default void onDynamicResourcesStatusChange(boolean enabled) { } - - /** - * 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(ModelResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery, ModelBakery.TextureGetter textureGetter) { - return originalModel; - } } diff --git a/src/main/java/org/embeddedt/modernfix/api/helpers/ModelHelpers.java b/src/main/java/org/embeddedt/modernfix/api/helpers/ModelHelpers.java deleted file mode 100644 index 32ae00b2..00000000 --- a/src/main/java/org/embeddedt/modernfix/api/helpers/ModelHelpers.java +++ /dev/null @@ -1,76 +0,0 @@ -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.dynamicresources.ModelBakeryHelpers; -import org.embeddedt.modernfix.util.DynamicMap; - -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 getBlockStateForLocation(ModelResourceLocation location) { - Optional blockOpt = BuiltInRegistries.BLOCK.getOptional(location.id()); - 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 getBlockStateForLocation(StateDefinition 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 createFakeTopLevelMap(BiFunction modelGetter) { - return new DynamicMap<>(ResourceLocation.class, 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) { - throw new UnsupportedOperationException("TODO"); - /* - 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); - } - }; - - */ - } -} diff --git a/src/main/java/org/embeddedt/modernfix/command/ModernFixCommands.java b/src/main/java/org/embeddedt/modernfix/command/ModernFixCommands.java index dac52423..63aa0821 100644 --- a/src/main/java/org/embeddedt/modernfix/command/ModernFixCommands.java +++ b/src/main/java/org/embeddedt/modernfix/command/ModernFixCommands.java @@ -4,6 +4,7 @@ import com.mojang.brigadier.CommandDispatcher; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.permissions.Permissions; import org.embeddedt.modernfix.duck.IProfilingServerFunctionManager; import static net.minecraft.commands.Commands.literal; @@ -11,7 +12,7 @@ import static net.minecraft.commands.Commands.literal; public class ModernFixCommands { public static void register(CommandDispatcher dispatcher) { dispatcher.register(literal("modernfix") - .then(literal("mcfunctions").requires(source -> source.hasPermission(3)) + .then(literal("mcfunctions").requires(source -> source.permissions().hasPermission(Permissions.COMMANDS_ADMIN)) .executes(context -> { ServerLevel level = context.getSource().getLevel(); if(level == null) { diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/chunk_deadlock/EntityMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/chunk_deadlock/EntityMixin.java deleted file mode 100644 index 1cf541f0..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/chunk_deadlock/EntityMixin.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.bugfix.chunk_deadlock; - -import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; -import net.minecraft.core.Holder; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.gameevent.GameEvent; -import org.embeddedt.modernfix.ModernFix; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; - -@Mixin(Entity.class) -public class EntityMixin { - /** - * @author embeddedt - * @reason When an entity is added to the world via the worldgen load path (ChunkMap#postLoadProtoChunk calling - * ServerLevel#addWorldGenChunkEntities), attempts to add a passenger result in a deadlock when the sculk event - * tries to raytrace blocks. To fix this, we skip firing the sculk event if the chunk the entity is within is not - * loaded. - */ - @WrapWithCondition(method = "addPassenger", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;gameEvent(Lnet/minecraft/core/Holder;Lnet/minecraft/world/entity/Entity;)V")) - private boolean onlyAddIfSelfChunkLoaded(Entity instance, Holder gameEvent, Entity entity) { - var chunkPos = instance.chunkPosition(); - if (instance.level() instanceof ServerLevel serverLevel && serverLevel.getChunkSource().getChunkNow(chunkPos.x, chunkPos.z) == null) { - ModernFix.LOGGER.warn("Skipped emitting ENTITY_MOUNT game event for entity {} as it would cause deadlock", instance.toString()); - return false; - } else { - return true; - } - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/ender_dragon_leak/EnderDragonRendererMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/ender_dragon_leak/EnderDragonRendererMixin.java deleted file mode 100644 index d3600b87..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/ender_dragon_leak/EnderDragonRendererMixin.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.bugfix.ender_dragon_leak; - -import net.minecraft.client.renderer.entity.EnderDragonRenderer; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -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(EnderDragonRenderer.class) -@ClientOnlyMixin -public abstract class EnderDragonRendererMixin { - @Shadow @Final private EnderDragonRenderer.DragonModel model; - - /** - * Prevent leaking the client world through the entity reference. - */ - @Inject(method = "render(Lnet/minecraft/world/entity/boss/enderdragon/EnderDragon;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At("RETURN")) - private void clearDragonEntityReference(CallbackInfo ci) { - this.model.entity = null; - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/entity_pose_stack/LivingEntityRendererMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/entity_pose_stack/LivingEntityRendererMixin.java deleted file mode 100644 index cfb4503d..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/entity_pose_stack/LivingEntityRendererMixin.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.bugfix.entity_pose_stack; - -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.renderer.entity.LivingEntityRenderer; -import net.neoforged.neoforge.client.event.RenderLivingEvent; -import net.neoforged.bus.api.Event; -import net.neoforged.bus.api.IEventBus; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(LivingEntityRenderer.class) -@ClientOnlyMixin -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)) - private Event fireCheckingPoseStack(IEventBus instance, Event event) { - PoseStack stack = ((RenderLivingEvent)event).getPoseStack(); - int size = ((PoseStackAccessor)stack).getPoseStack().size(); - instance.post(event); - if (((RenderLivingEvent.Pre)event).isCanceled()) { - // Pop the stack if someone pushed it in the event - while (((PoseStackAccessor)stack).getPoseStack().size() > size) { - stack.popPose(); - } - } - return event; - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/entity_pose_stack/PlayerRendererMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/entity_pose_stack/PlayerRendererMixin.java deleted file mode 100644 index 770b4d92..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/entity_pose_stack/PlayerRendererMixin.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.bugfix.entity_pose_stack; - -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.renderer.entity.player.PlayerRenderer; -import net.neoforged.bus.api.Event; -import net.neoforged.bus.api.IEventBus; -import net.neoforged.neoforge.client.event.RenderPlayerEvent; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(PlayerRenderer.class) -@ClientOnlyMixin -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)) - private Event fireCheckingPoseStack(IEventBus instance, Event event) { - PoseStack stack = ((RenderPlayerEvent)event).getPoseStack(); - int size = ((PoseStackAccessor)stack).getPoseStack().size(); - instance.post(event); - if (((RenderPlayerEvent.Pre)event).isCanceled()) { - // Pop the stack if someone pushed it in the event - while (((PoseStackAccessor)stack).getPoseStack().size() > size) { - stack.popPose(); - } - } - return event; - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/entity_pose_stack/PoseStackAccessor.java b/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/entity_pose_stack/PoseStackAccessor.java deleted file mode 100644 index 6aebaf60..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/entity_pose_stack/PoseStackAccessor.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.bugfix.entity_pose_stack; - -import com.mojang.blaze3d.vertex.PoseStack; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.Deque; - -@Mixin(PoseStack.class) -@ClientOnlyMixin -public interface PoseStackAccessor { - @Accessor - Deque getPoseStack(); -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/missing_block_entities/LevelChunkMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/missing_block_entities/LevelChunkMixin.java index 923ca57c..c833078c 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/missing_block_entities/LevelChunkMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/missing_block_entities/LevelChunkMixin.java @@ -2,17 +2,16 @@ package org.embeddedt.modernfix.common.mixin.bugfix.missing_block_entities; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; -import net.minecraft.core.Registry; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.chunk.PalettedContainerFactory; import net.minecraft.world.level.chunk.UpgradeData; import net.minecraft.world.level.levelgen.blending.BlendingData; import org.embeddedt.modernfix.ModernFix; @@ -38,14 +37,14 @@ public abstract class LevelChunkMixin extends ChunkAccess { @Shadow @Nullable public abstract BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EntityCreationType creationType); - public LevelChunkMixin(ChunkPos chunkPos, UpgradeData upgradeData, LevelHeightAccessor levelHeightAccessor, Registry biomeRegistry, long inhabitedTime, @Nullable LevelChunkSection[] sections, @Nullable BlendingData blendingData) { - super(chunkPos, upgradeData, levelHeightAccessor, biomeRegistry, inhabitedTime, sections, blendingData); + public LevelChunkMixin(ChunkPos chunkPos, UpgradeData upgradeData, LevelHeightAccessor levelHeightAccessor, PalettedContainerFactory palettedContainerFactory, long inhabitedTime, LevelChunkSection @org.jspecify.annotations.Nullable [] sections, @org.jspecify.annotations.Nullable BlendingData blendingData) { + super(chunkPos, upgradeData, levelHeightAccessor, palettedContainerFactory, inhabitedTime, sections, blendingData); } @Inject(method = "replaceWithPacketData", at = @At("RETURN")) private void validateBlockEntitiesInChunk(CallbackInfo ci) { // No reason to check in singleplayer or on the integrated server - if (this.level.isClientSide && !Minecraft.getInstance().isLocalServer()) { + if (this.level.isClientSide() && !Minecraft.getInstance().isLocalServer()) { for (int i = 0; i < this.sections.length; i++) { var section = this.sections[i]; try { diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/world_leaks/MinecraftMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/world_leaks/MinecraftMixin.java index 7b5f8860..7012c64e 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/world_leaks/MinecraftMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/world_leaks/MinecraftMixin.java @@ -24,7 +24,7 @@ public class MinecraftMixin { /** * To mitigate the effect of leaked client worlds, clear most of the data structures that waste memory. */ - @Inject(method = "disconnect(Lnet/minecraft/client/gui/screens/Screen;Z)V", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/client/Minecraft;level:Lnet/minecraft/client/multiplayer/ClientLevel;")) + @Inject(method = "disconnect(Lnet/minecraft/client/gui/screens/Screen;ZZ)V", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/client/Minecraft;level:Lnet/minecraft/client/multiplayer/ClientLevel;")) private void clearLevelDataForLeaks(CallbackInfo ci) { if(this.level != null) { try { diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/core/BootstrapClientMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/core/BootstrapClientMixin.java deleted file mode 100644 index cc7fe407..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/core/BootstrapClientMixin.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.core; - -import net.minecraft.client.renderer.RenderType; -import net.minecraft.server.Bootstrap; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -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.callback.CallbackInfo; - -@Mixin(Bootstrap.class) -@ClientOnlyMixin -public class BootstrapClientMixin { - /** - * Hack to workaround RenderStateShard deadlock (by loading it early on a single thread). We use validate - * here to ensure Forge registries are initialized. - */ - @Inject(method = "validate", at = @At("HEAD")) - private static void loadClientClasses(CallbackInfo ci) { - RenderType.solid(); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/core/BootstrapMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/core/BootstrapMixin.java index 099e37bc..ddaad6f2 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/core/BootstrapMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/core/BootstrapMixin.java @@ -5,6 +5,7 @@ import org.embeddedt.modernfix.util.TimeFormatter; import org.slf4j.Logger; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.MixinEnvironment; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -22,6 +23,9 @@ public class BootstrapMixin { private static void doModernFixBootstrap(CallbackInfo ci) { if(!isBootstrapped) { LOGGER.info("ModernFix reached bootstrap stage ({} after launch)", TimeFormatter.formatNanos(ManagementFactory.getRuntimeMXBean().getUptime() * 1000L * 1000L)); + if (Boolean.getBoolean("modernfix.auditMixinsAtStart")) { + MixinEnvironment.getCurrentEnvironment().audit(); + } } } } diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/core/MinecraftServerMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/core/MinecraftServerMixin.java index b6350a91..f59f01e9 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/core/MinecraftServerMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/core/MinecraftServerMixin.java @@ -1,7 +1,7 @@ package org.embeddedt.modernfix.common.mixin.core; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; -import net.minecraft.Util; +import net.minecraft.util.Util; import net.minecraft.server.MinecraftServer; import org.embeddedt.modernfix.duck.ITimeTrackingServer; import org.embeddedt.modernfix.neoforge.load.MinecraftServerReloadTracker; @@ -36,7 +36,7 @@ public class MinecraftServerMixin implements ITimeTrackingServer { return mfix$lastTickStartTime; } - @Inject(method = "runServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;tickServer(Ljava/util/function/BooleanSupplier;)V")) + @Inject(method = "runServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;processPacketsAndTick(Z)V")) private void trackTickTime(CallbackInfo ci) { mfix$lastTickStartTime = Util.getMillis(); } diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/feature/cause_lag_by_disabling_threads/UtilMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/feature/cause_lag_by_disabling_threads/UtilMixin.java index a8b452bd..7378f2d8 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/feature/cause_lag_by_disabling_threads/UtilMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/feature/cause_lag_by_disabling_threads/UtilMixin.java @@ -1,16 +1,15 @@ package org.embeddedt.modernfix.common.mixin.feature.cause_lag_by_disabling_threads; -import net.minecraft.Util; +import net.minecraft.TracingExecutor; +import net.minecraft.util.Util; import org.embeddedt.modernfix.util.DirectExecutorService; 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 java.util.concurrent.ExecutorService; - @Mixin(Util.class) public class UtilMixin { @Shadow @Final @Mutable - private static final ExecutorService BACKGROUND_EXECUTOR = new DirectExecutorService(); + private static final TracingExecutor BACKGROUND_EXECUTOR = new TracingExecutor(new DirectExecutorService()); } diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/feature/mcfunction_profiling/ServerFunctionManagerMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/feature/mcfunction_profiling/ServerFunctionManagerMixin.java index 58629f67..a7b5afb7 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/feature/mcfunction_profiling/ServerFunctionManagerMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/feature/mcfunction_profiling/ServerFunctionManagerMixin.java @@ -7,7 +7,7 @@ import com.llamalad7.mixinextras.sugar.ref.LocalRef; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.functions.CommandFunction; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.ServerFunctionManager; import org.embeddedt.modernfix.duck.IProfilingServerFunctionManager; import org.spongepowered.asm.mixin.Final; @@ -25,17 +25,17 @@ import java.util.Map; @Mixin(ServerFunctionManager.class) public class ServerFunctionManagerMixin implements IProfilingServerFunctionManager { - @Shadow @Final private static ResourceLocation TICK_FUNCTION_TAG; + @Shadow @Final private static Identifier TICK_FUNCTION_TAG; - private final Map mfix$functionWatches = new Object2ObjectOpenHashMap<>(); + private final Map mfix$functionWatches = new Object2ObjectOpenHashMap<>(); @Inject(method = "executeTagFunctions", at = @At("HEAD")) - private void resetWatches(Collection> functionObjects, ResourceLocation identifier, CallbackInfo ci) { + private void resetWatches(Collection> functionObjects, Identifier identifier, CallbackInfo ci) { mfix$functionWatches.values().forEach(Stopwatch::reset); } @Inject(method = "executeTagFunctions", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/ServerFunctionManager;execute(Lnet/minecraft/commands/functions/CommandFunction;Lnet/minecraft/commands/CommandSourceStack;)V")) - private void startWatch(Collection> functionObjects, ResourceLocation identifier, CallbackInfo ci, @Local(ordinal = 0) CommandFunction function, @Share("stopwatch") LocalRef watchRef) { + private void startWatch(Collection> functionObjects, Identifier identifier, CallbackInfo ci, @Local(ordinal = 0) CommandFunction function, @Share("stopwatch") LocalRef watchRef) { watchRef.set(null); if (identifier == TICK_FUNCTION_TAG) { var watch = mfix$functionWatches.computeIfAbsent(function.id(), i -> Stopwatch.createUnstarted()); @@ -45,7 +45,7 @@ public class ServerFunctionManagerMixin implements IProfilingServerFunctionManag } @Inject(method = "executeTagFunctions", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/ServerFunctionManager;execute(Lnet/minecraft/commands/functions/CommandFunction;Lnet/minecraft/commands/CommandSourceStack;)V", shift = At.Shift.AFTER)) - private void stopWatch(Collection> functionObjects, ResourceLocation identifier, CallbackInfo ci, @Share("stopwatch") LocalRef watchRef) { + private void stopWatch(Collection> functionObjects, Identifier identifier, CallbackInfo ci, @Share("stopwatch") LocalRef watchRef) { var watch = watchRef.get(); if (watch != null && watch.isRunning()) { watch.stop(); @@ -53,14 +53,14 @@ public class ServerFunctionManagerMixin implements IProfilingServerFunctionManag } @Inject(method = "executeTagFunctions", at = @At("RETURN")) - private void pruneUnusedWatches(Collection> functionObjects, ResourceLocation identifier, CallbackInfo ci) { + private void pruneUnusedWatches(Collection> functionObjects, Identifier identifier, CallbackInfo ci) { mfix$functionWatches.values().removeIf(watch -> watch.elapsed().isZero()); } @Override public String mfix$getProfilingResults() { var list = new ArrayList<>(mfix$functionWatches.entrySet()); - list.sort(Comparator., Duration>comparing(e -> e.getValue().elapsed()).reversed()); + list.sort(Comparator., Duration>comparing(e -> e.getValue().elapsed()).reversed()); StringBuilder sb = new StringBuilder(); for (var entry : list) { sb.append(entry.getKey().toString()); diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/feature/measure_time/ProfiledReloadInstanceMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/feature/measure_time/ProfiledReloadInstanceMixin.java index 33f4d60f..be8d906e 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/feature/measure_time/ProfiledReloadInstanceMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/feature/measure_time/ProfiledReloadInstanceMixin.java @@ -39,7 +39,7 @@ public class ProfiledReloadInstanceMixin { @ModifyVariable(method = "finish", ordinal = 0, argsOnly = true, at = @At("HEAD")) private List sortStates(List datapoints) { datapoints = new ArrayList<>(datapoints); - datapoints.sort(Comparator.comparingLong(s -> s.preparationNanos.get() + s.reloadNanos.get()).reversed()); + datapoints.sort(Comparator.comparingLong(s -> s.preparationNanos().get() + s.reloadNanos().get()).reversed()); return datapoints; } } diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/feature/registry_event_progress/GameDataMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/feature/registry_event_progress/GameDataMixin.java index 093cd91e..78ba5a30 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/feature/registry_event_progress/GameDataMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/feature/registry_event_progress/GameDataMixin.java @@ -25,7 +25,7 @@ public class GameDataMixin { } RegisterEvent registryEvent = (RegisterEvent)event; // We control phases ourselves so we can make a separate progress bar for each phase. - String registryName = registryEvent.getRegistryKey().location().toString(); + String registryName = registryEvent.getRegistryKey().identifier().toString(); for(EventPriority phase : EventPriority.values()) { // FIXME need to use prepend rather than append for it to be visible for now var pb = StartupNotificationManager.prependProgressBar(registryName, ModList.get().size()); diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_strongholds/ChunkGeneratorMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_strongholds/ChunkGeneratorMixin.java deleted file mode 100644 index f9ca5195..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_strongholds/ChunkGeneratorMixin.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.cache_strongholds; - -import net.minecraft.Util; -import net.minecraft.core.Holder; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.chunk.ChunkGeneratorStructureState; -import net.minecraft.world.level.levelgen.structure.StructureSet; -import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement; -import org.embeddedt.modernfix.ModernFix; -import org.embeddedt.modernfix.duck.IChunkGenerator; -import org.embeddedt.modernfix.duck.IServerLevel; -import org.embeddedt.modernfix.world.StrongholdLocationCache; -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.callback.CallbackInfoReturnable; - -import java.lang.ref.WeakReference; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -@Mixin(ChunkGeneratorStructureState.class) -public class ChunkGeneratorMixin implements IChunkGenerator { - private WeakReference mfix$serverLevel; - - @Override - public void mfix$setAssociatedServerLevel(ServerLevel level) { - mfix$serverLevel = new WeakReference<>(level); - } - - @Inject(method = "generateRingPositions", at = @At("HEAD"), cancellable = true) - private void useCachedDataIfAvailable(Holder structureSet, ConcentricRingsStructurePlacement placement, CallbackInfoReturnable>> cir) { - if(placement.count() == 0) - return; - ServerLevel level = searchLevel(); - if(level == null) - return; - StrongholdLocationCache cache = ((IServerLevel)level).mfix$getStrongholdCache(); - List positions = cache.getChunkPosList(); - if(positions.isEmpty()) - return; - ModernFix.LOGGER.debug("Loaded stronghold cache for dimension {} with {} positions", level.dimension().location(), positions.size()); - cir.setReturnValue(CompletableFuture.completedFuture(positions)); - } - - private ServerLevel searchLevel() { - if(mfix$serverLevel != null) - return mfix$serverLevel.get(); - else - return null; - } - - @Inject(method = "generateRingPositions", at = @At("RETURN"), cancellable = true) - private void saveCachedData(Holder structureSet, ConcentricRingsStructurePlacement placement, CallbackInfoReturnable>> cir) { - cir.setReturnValue(cir.getReturnValue().thenApplyAsync(list -> { - if(list.size() == 0) - return list; - ServerLevel level = searchLevel(); - if(level != null) { - StrongholdLocationCache cache = ((IServerLevel)level).mfix$getStrongholdCache(); - cache.setChunkPosList(list); - ModernFix.LOGGER.debug("Saved stronghold cache for dimension {}", level.dimension().location()); - } - return list; - }, Util.backgroundExecutor())); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_strongholds/ServerLevelMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_strongholds/ServerLevelMixin.java deleted file mode 100644 index 2aac7c47..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_strongholds/ServerLevelMixin.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.cache_strongholds; - -import net.minecraft.core.Holder; -import net.minecraft.core.RegistryAccess; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.level.ServerChunkCache; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.profiling.ProfilerFiller; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.chunk.ChunkGeneratorStructureState; -import net.minecraft.world.level.dimension.DimensionType; -import net.minecraft.world.level.storage.DimensionDataStorage; -import net.minecraft.world.level.storage.WritableLevelData; -import org.embeddedt.modernfix.duck.IChunkGenerator; -import org.embeddedt.modernfix.duck.IServerLevel; -import org.embeddedt.modernfix.world.StrongholdLocationCache; -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.function.Supplier; - -@Mixin(ServerLevel.class) -public abstract class ServerLevelMixin extends Level implements IServerLevel { - protected ServerLevelMixin(WritableLevelData arg, ResourceKey arg2, RegistryAccess arg3, Holder arg4, Supplier supplier, boolean bl, boolean bl2, long l, int i) { - super(arg, arg2, arg3, arg4, supplier, bl, bl2, l, i); - } - - @Shadow public abstract DimensionDataStorage getDataStorage(); - - @Shadow @Final private ServerChunkCache chunkSource; - private StrongholdLocationCache mfix$strongholdCache; - - /** - * Initialize the stronghold cache but don't force any structure generation yet. - */ - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/ChunkGeneratorStructureState;ensureStructuresGenerated()V")) - private void hookStrongholdCache(ChunkGeneratorStructureState generator) { - ((IChunkGenerator)generator).mfix$setAssociatedServerLevel((ServerLevel)(Object)this); - } - - /** - * Now start the stronghold generation process. - */ - @Inject(method = "", at = @At("TAIL")) - private void ensureGeneration(CallbackInfo ci) { - mfix$strongholdCache = this.getDataStorage().computeIfAbsent( - StrongholdLocationCache.factory((ServerLevel)(Object)this), - StrongholdLocationCache.getFileId(this.dimensionTypeRegistration())); - this.chunkSource.getGeneratorState().ensureStructuresGenerated(); - } - - @Override - public StrongholdLocationCache mfix$getStrongholdCache() { - return mfix$strongholdCache; - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compact_bit_storage/PalettedContainerMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compact_bit_storage/PalettedContainerMixin.java index 5edb5890..293eb72b 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compact_bit_storage/PalettedContainerMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compact_bit_storage/PalettedContainerMixin.java @@ -1,6 +1,7 @@ package org.embeddedt.modernfix.common.mixin.perf.compact_bit_storage; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.level.chunk.PaletteResize; import net.minecraft.world.level.chunk.PalettedContainer; import org.jetbrains.annotations.Nullable; import org.objectweb.asm.Opcodes; @@ -40,7 +41,7 @@ public abstract class PalettedContainerMixin { return; } this.data = this.createOrReuseData(null, 0); - this.data.palette().idFor(value); + this.data.palette().idFor(value, (PaletteResize)this); } } } diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compact_mojang_registries/BlockStateDataMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compact_mojang_registries/BlockStateDataMixin.java index eb85f08c..fed1cfd0 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compact_mojang_registries/BlockStateDataMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/compact_mojang_registries/BlockStateDataMixin.java @@ -22,6 +22,7 @@ public class BlockStateDataMixin { * @author embeddedt * @reason Reduce memory use of these constant CompoundTags via aggressive interning. */ + /* @ModifyExpressionValue(method = "parse", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/TagParser;parseTag(Ljava/lang/String;)Lnet/minecraft/nbt/CompoundTag;")) private static CompoundTag compactTag(CompoundTag tag) { if (TAG_INTERNER == null) { @@ -40,6 +41,8 @@ public class BlockStateDataMixin { return new CompoundTag(Map.ofEntries(entries)); } + */ + @Inject(method = "", at = @At("RETURN")) private static void clearInterner(CallbackInfo ci) { if (TAG_INTERNER != null) { diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/CreateWorldScreenMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/CreateWorldScreenMixin.java index 16a18dd8..acd42740 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/CreateWorldScreenMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/CreateWorldScreenMixin.java @@ -17,7 +17,7 @@ public class CreateWorldScreenMixin { return ModernFix.resourceReloadExecutor(); } - @ModifyArg(method = "openFresh", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/WorldLoader;load(Lnet/minecraft/server/WorldLoader$InitConfig;Lnet/minecraft/server/WorldLoader$WorldDataSupplier;Lnet/minecraft/server/WorldLoader$ResultFactory;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"), index = 3) + @ModifyArg(method = "openCreateWorldScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/WorldLoader;load(Lnet/minecraft/server/WorldLoader$InitConfig;Lnet/minecraft/server/WorldLoader$WorldDataSupplier;Lnet/minecraft/server/WorldLoader$ResultFactory;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"), index = 3) private static Executor getCreationExecutorService(Executor e) { return ModernFix.resourceReloadExecutor(); } diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/MinecraftMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/MinecraftMixin.java index 5d287c8b..830b530e 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/MinecraftMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/MinecraftMixin.java @@ -1,5 +1,6 @@ package org.embeddedt.modernfix.common.mixin.perf.dedicated_reload_executor; +import net.minecraft.TracingExecutor; import net.minecraft.client.Minecraft; import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; @@ -7,13 +8,11 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import java.util.concurrent.ExecutorService; - @Mixin(Minecraft.class) @ClientOnlyMixin public class MinecraftMixin { - @Redirect(method = { "", "reloadResourcePacks(ZLnet/minecraft/client/Minecraft$GameLoadCookie;)Ljava/util/concurrent/CompletableFuture;" }, at = @At(value = "INVOKE", target = "Lnet/minecraft/Util;backgroundExecutor()Ljava/util/concurrent/ExecutorService;", ordinal = 0)) - private ExecutorService getResourceReloadExecutor() { + @Redirect(method = { "", "reloadResourcePacks(ZLnet/minecraft/client/Minecraft$GameLoadCookie;)Ljava/util/concurrent/CompletableFuture;" }, at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Util;backgroundExecutor()Lnet/minecraft/TracingExecutor;", ordinal = 0)) + private TracingExecutor getResourceReloadExecutor() { return ModernFix.resourceReloadExecutor(); } } diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/MinecraftServerMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/MinecraftServerMixin.java index e0f53533..7516a790 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/MinecraftServerMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dedicated_reload_executor/MinecraftServerMixin.java @@ -10,7 +10,7 @@ import java.util.concurrent.Executor; @Mixin(MinecraftServer.class) public class MinecraftServerMixin { - @ModifyArg(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/ReloadableServerResources;loadResources(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;ILjava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"), index = 5) + @ModifyArg(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/ReloadableServerResources;loadResources(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/core/LayeredRegistryAccess;Ljava/util/List;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;Lnet/minecraft/server/permissions/PermissionSet;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"), index = 6) private Executor getReloadExecutor(Executor asyncExecutor) { return ModernFix.resourceReloadExecutor(); } diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/deduplicate_wall_shapes/WallBlockMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/deduplicate_wall_shapes/WallBlockMixin.java deleted file mode 100644 index 09532efc..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/deduplicate_wall_shapes/WallBlockMixin.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.deduplicate_wall_shapes; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.mojang.datafixers.util.Pair; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.WallBlock; -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 net.minecraft.world.phys.shapes.VoxelShape; -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.callback.CallbackInfoReturnable; - -import java.util.HashMap; -import java.util.Map; - -/** - * Most wall blocks use the default set of vanilla properties, and the default sizes for their shapes. This means - * there is no need to reconstruct a separate VoxelShape instance for each wall, we can just repurpose the - * same shape instances. To do this we can cache a mapping between a state (represented only as its prop->value map) - * and the desired shape, and generate the BlockState->VoxelShape map from this for each block. - */ -@Mixin(WallBlock.class) -public abstract class WallBlockMixin extends Block { - private static Map, Pair, Comparable>, VoxelShape>, StateDefinition>> CACHE_BY_SHAPE_VALS = new HashMap<>(); - - public WallBlockMixin(Properties properties) { - super(properties); - } - - @Inject(method = "makeShapes", at = @At("HEAD"), cancellable = true) - private synchronized void useCachedShapeMap(float f1, float f2, float f3, float f4, float f5, float f6, CallbackInfoReturnable> cir) { - ImmutableList key = ImmutableList.of(f1, f2, f3, f4, f5, f6); - Pair, Comparable>, VoxelShape>, StateDefinition> cache = CACHE_BY_SHAPE_VALS.get(key); - // require the properties to be identical - if(cache == null || !cache.getSecond().getProperties().equals(this.stateDefinition.getProperties())) - return; - ImmutableMap.Builder builder = ImmutableMap.builder(); - for(BlockState state : this.stateDefinition.getPossibleStates()) { - VoxelShape shape = cache.getFirst().get(state.getValues()); - if(shape == null) - return; // fallback to vanilla logic - builder.put(state, shape); - } - cir.setReturnValue(builder.build()); - } - - @Inject(method = "makeShapes", at = @At("RETURN")) - private synchronized void storeCachedShapesByProperty(float f1, float f2, float f3, float f4, float f5, float f6, CallbackInfoReturnable> cir) { - // never populate cache as a non-vanilla block - if((Class)this.getClass() != WallBlock.class) - return; - ImmutableList key = ImmutableList.of(f1, f2, f3, f4, f5, f6); - if(!CACHE_BY_SHAPE_VALS.containsKey(key)) { - Map, Comparable>, VoxelShape> cacheByProperties = new HashMap<>(); - Map shapeMap = cir.getReturnValue(); - for(Map.Entry entry : shapeMap.entrySet()) { - cacheByProperties.put(entry.getKey().getValues(), entry.getValue()); - } - CACHE_BY_SHAPE_VALS.put(key, Pair.of(cacheByProperties, this.stateDefinition)); - } - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockModelShaperMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockModelShaperMixin.java deleted file mode 100644 index 40df98f0..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockModelShaperMixin.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; - -import net.minecraft.client.renderer.block.BlockModelShaper; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.ModelManager; -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.embeddedt.modernfix.duck.IModelHoldingBlockState; -import org.embeddedt.modernfix.dynamicresources.ModelLocationCache; -import org.embeddedt.modernfix.util.DynamicOverridableMap; -import org.spongepowered.asm.mixin.*; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.Map; - -@Mixin(BlockModelShaper.class) -@ClientOnlyMixin -public class BlockModelShaperMixin { - @Shadow @Final private ModelManager modelManager; - - @Shadow - private Map modelByStateCache; - - @Inject(method = { "", "replaceCache" }, at = @At("RETURN")) - private void replaceModelMap(CallbackInfo ci) { - // replace the backing map for mods which will access it - this.modelByStateCache = new DynamicOverridableMap<>(BlockState.class, state -> modelManager.getModel(ModelLocationCache.get(state))); - // Clear the cached models on blockstate objects - for(Block block : BuiltInRegistries.BLOCK) { - for(BlockState state : block.getStateDefinition().getPossibleStates()) { - if(state instanceof IModelHoldingBlockState modelHolder) { - modelHolder.mfix$setModel(null); - } - } - } - } - - private BakedModel cacheBlockModel(BlockState state) { - // Do all model system accesses in the unlocked path - ModelResourceLocation mrl = ModelLocationCache.get(state); - BakedModel model = mrl == null ? null : modelManager.getModel(mrl); - if (model == null) { - model = modelManager.getMissingModel(); - } - - return model; - } - - /** - * @author embeddedt - * @reason get the model from the dynamic model provider - */ - @Overwrite - public BakedModel getBlockModel(BlockState state) { - if(state instanceof IModelHoldingBlockState modelHolder) { - BakedModel model = modelHolder.mfix$getModel(); - - if(model != null) { - return model; - } - - model = this.cacheBlockModel(state); - modelHolder.mfix$setModel(model); - return model; - } else { - return this.cacheBlockModel(state); - } - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockStateBaseMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockStateBaseMixin.java deleted file mode 100644 index 0221e374..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockStateBaseMixin.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; - -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.world.level.block.state.BlockBehaviour; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.embeddedt.modernfix.duck.IModelHoldingBlockState; -import org.spongepowered.asm.mixin.Mixin; - -import java.lang.ref.SoftReference; - -@Mixin(BlockBehaviour.BlockStateBase.class) -@ClientOnlyMixin -public class BlockStateBaseMixin implements IModelHoldingBlockState { - private volatile SoftReference mfix$model; - - @Override - public BakedModel mfix$getModel() { - var ref = mfix$model; - return ref != null ? ref.get() : null; - } - - @Override - public void mfix$setModel(BakedModel model) { - mfix$model = model != null ? new SoftReference<>(model) : null; - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockStateModelLoaderMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockStateModelLoaderMixin.java deleted file mode 100644 index 8fc41b55..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockStateModelLoaderMixin.java +++ /dev/null @@ -1,117 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.collect.ImmutableList; -import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import it.unimi.dsi.fastutil.Pair; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntMaps; -import it.unimi.dsi.fastutil.objects.ReferenceObjectImmutablePair; -import net.minecraft.client.color.block.BlockColors; -import net.minecraft.client.renderer.block.model.BlockModelDefinition; -import net.minecraft.client.resources.model.BlockStateModelLoader; -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.client.resources.model.UnbakedModel; -import net.minecraft.core.DefaultedRegistry; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.profiling.ProfilerFiller; -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.annotation.ClientOnlyMixin; -import org.embeddedt.modernfix.duck.IBlockStateModelLoader; -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.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.Iterator; -import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.function.BiConsumer; -import java.util.function.Predicate; - -@Mixin(BlockStateModelLoader.class) -@ClientOnlyMixin -public abstract class BlockStateModelLoaderMixin implements IBlockStateModelLoader { - @Shadow protected abstract void loadBlockStateDefinitions(ResourceLocation resourceLocation, StateDefinition stateDefinition); - - @Shadow @Mutable @Final private Object2IntMap modelGroups; - - private ImmutableList filteredStates; - - @Inject(method = "", at = @At("RETURN")) - private void makeModelGroupsSynchronized(Map map, ProfilerFiller profilerFiller, UnbakedModel unbakedModel, BlockColors blockColors, BiConsumer biConsumer, CallbackInfo ci) { - this.modelGroups = Object2IntMaps.synchronize(this.modelGroups); - } - - @Override - public void loadSpecificBlock(ModelResourceLocation location) { - var optionalBlock = BuiltInRegistries.BLOCK.getOptional(location.id()); - if(optionalBlock.isPresent()) { - // embeddedt note - filtering is currently disabled as it's quite inefficient to do vs. just loading - // the extra models and letting LRU deal with it - /* - try { - // Only filter states if we are in a world and not in the loading overlay - filteredStates = (Minecraft.getInstance().getOverlay() == null && Minecraft.getInstance().level != null) ? ModelBakeryHelpers.getBlockStatesForMRL(optionalBlock.get().getStateDefinition(), location) : null; - } catch(RuntimeException e) { - ModernFix.LOGGER.error("Exception filtering states on {}", location, e); - filteredStates = null; - } - */ - try { - this.loadBlockStateDefinitions(location.id(), optionalBlock.get().getStateDefinition()); - } finally { - filteredStates = null; - } - } - } - - @Redirect(method = "loadAllBlockStates", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/DefaultedRegistry;iterator()Ljava/util/Iterator;")) - private Iterator skipIteratingBlocks(DefaultedRegistry instance) { - return Collections.emptyIterator(); - } - - @Redirect(method = "loadBlockStateDefinitions", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/StateDefinition;getPossibleStates()Lcom/google/common/collect/ImmutableList;")) - private ImmutableList getFilteredStates(StateDefinition instance) { - return this.filteredStates != null ? this.filteredStates : instance.getPossibleStates(); - } - - // Add some caching around key hot paths - - private final Cache, BlockModelDefinition> cachedBlockModelDefs = CacheBuilder.newBuilder() - .maximumSize(100) - .build(); - - private static final Cache, String>, Predicate> cachedBlockStatePredicates = CacheBuilder.newBuilder() - .maximumSize(100) - .build(); - - @WrapOperation(method = "loadBlockStateDefinitions", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/BlockStateModelLoader$LoadedJson;parse(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/renderer/block/model/BlockModelDefinition$Context;)Lnet/minecraft/client/renderer/block/model/BlockModelDefinition;")) - private BlockModelDefinition avoidMultipleParses(BlockStateModelLoader.LoadedJson instance, ResourceLocation blockStateId, BlockModelDefinition.Context context, Operation original) { - try { - return cachedBlockModelDefs.get(ReferenceObjectImmutablePair.of(instance, blockStateId), () -> original.call(instance, blockStateId, context)); - } catch (ExecutionException e) { - throw new RuntimeException(e); - } - } - - @WrapMethod(method = "predicate") - private static Predicate memoizePredicate(StateDefinition stateDefentition, String properties, Operation> original) { - try { - return cachedBlockStatePredicates.get(Pair.of(stateDefentition, properties), () -> original.call(stateDefentition, properties)); - } catch (ExecutionException e) { - throw new RuntimeException(e); - } - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ForgeHooksClientMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ForgeHooksClientMixin.java deleted file mode 100644 index ea090260..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ForgeHooksClientMixin.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; - -import com.google.common.base.Stopwatch; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.neoforged.bus.api.Event; -import net.neoforged.fml.ModContainer; -import net.neoforged.fml.ModList; -import net.neoforged.fml.ModLoader; -import net.neoforged.fml.util.ObfuscationReflectionHelper; -import net.neoforged.neoforge.client.ClientHooks; -import net.neoforged.neoforge.client.event.ModelEvent; -import org.embeddedt.modernfix.ModernFix; -import org.embeddedt.modernfix.neoforge.dynresources.ModelBakeEventHelper; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -import java.lang.reflect.Method; -import java.time.Duration; -import java.util.Comparator; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -@Mixin(ClientHooks.class) -public class ForgeHooksClientMixin { - /** - * Generate a more realistic keySet that contains every item and block model location, to help with mod compat. - */ - @Redirect(method = "onModifyBakingResult", at = @At(value = "INVOKE", target = "Lnet/neoforged/fml/ModLoader;postEvent(Lnet/neoforged/bus/api/Event;)V"), remap = false) - private static void postNamespacedKeySetEvent(Event event) { - if(ModLoader.hasErrors()) - return; - ModelEvent.ModifyBakingResult bakeEvent = ((ModelEvent.ModifyBakingResult)event); - Stopwatch globalTimer = Stopwatch.createStarted(); - Stopwatch selfTimer = Stopwatch.createStarted(); - ModelBakeEventHelper helper = new ModelBakeEventHelper(bakeEvent.getModels()); - selfTimer.stop(); - Method acceptEv = ObfuscationReflectionHelper.findMethod(ModContainer.class, "acceptEvent", Event.class); - Map times = new Object2ObjectOpenHashMap<>(); - times.put("modernfix", selfTimer); - ModList.get().forEachModContainer((id, mc) -> { - Map newRegistry = helper.wrapRegistry(id); - ModelEvent.ModifyBakingResult postedEvent = new ModelEvent.ModifyBakingResult(newRegistry, bakeEvent.getTextureGetter(), bakeEvent.getModelBakery()); - Stopwatch timer = times.computeIfAbsent(id, $ -> Stopwatch.createUnstarted()); - timer.start(); - try { - acceptEv.invoke(mc, postedEvent); - } catch(ReflectiveOperationException e) { - e.printStackTrace(); - } - timer.stop(); - }); - globalTimer.stop(); - if (globalTimer.elapsed(TimeUnit.SECONDS) >= 1) { - ModernFix.LOGGER.warn("Posting dynamic ModelEvent.ModifyBakingResult to mods took {}, breakdown below:", globalTimer); - times.entrySet().stream() - .sorted(Comparator., Duration>comparing(e -> e.getValue().elapsed()).reversed()) - .filter(e -> e.getValue().elapsed(TimeUnit.MILLISECONDS) > 50) - .forEach(entry -> { - ModernFix.LOGGER.warn(" {}: {}", entry.getKey(), entry.getValue().toString()); - }); - } - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemModelMesherForgeMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemModelMesherForgeMixin.java deleted file mode 100644 index e96e8e7b..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemModelMesherForgeMixin.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.embeddedt.modernfix.common.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 locations; - - private Map overrideLocations; - - private final DynamicModelCache 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 = "", 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(); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemModelShaperMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemModelShaperMixin.java deleted file mode 100644 index e47f5fee..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemModelShaperMixin.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import net.minecraft.client.renderer.ItemModelShaper; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.ModelManager; -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.embeddedt.modernfix.dynamicresources.DynamicModelCache; -import org.embeddedt.modernfix.dynamicresources.ModelLocationCache; -import org.embeddedt.modernfix.util.DynamicInt2ObjectMap; -import org.spongepowered.asm.mixin.*; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.HashMap; -import java.util.Map; - -@Mixin(ItemModelShaper.class) -@ClientOnlyMixin -public abstract class ItemModelShaperMixin { - - @Shadow public abstract ModelManager getModelManager(); - - @Shadow @Final @Mutable private Int2ObjectMap shapesCache; - - private Map overrideLocationsVanilla; - - public ItemModelShaperMixin() { - super(); - } - - private static final ModelResourceLocation SENTINEL_VANILLA = new ModelResourceLocation(ResourceLocation.fromNamespaceAndPath("modernfix", "sentinel"), "sentinel"); - - private final DynamicModelCache mfix$itemModelCache = new DynamicModelCache<>(k -> this.mfix$getModelForItem((Item)k), true); - - @Inject(method = "", at = @At("RETURN")) - private void replaceLocationMap(CallbackInfo ci) { - overrideLocationsVanilla = new HashMap<>(); - this.shapesCache = new DynamicInt2ObjectMap<>(index -> getModelManager().getModel(ModelLocationCache.get(Item.byId(index)))); - } - - @Unique - private ModelResourceLocation mfix$getLocation(Item item) { - ModelResourceLocation map = overrideLocationsVanilla.getOrDefault(item, SENTINEL_VANILLA); - if(map == SENTINEL_VANILLA) { - /* generate the appropriate location from our cache */ - map = ModelLocationCache.get(item); - } - return map; - } - - - private BakedModel mfix$getModelForItem(Item item) { - ModelResourceLocation map = mfix$getLocation(item); - 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 - public BakedModel getItemModel(Item item) { - return this.mfix$itemModelCache.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 - public void register(Item item, ModelResourceLocation location) { - overrideLocationsVanilla.put(item, location); - } - - /** - * @author embeddedt - * @reason Disable cache rebuilding (with dynamic loading, that would generate - * all models). - **/ - @Overwrite - public void rebuildCache() { - this.mfix$itemModelCache.clear(); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemRendererMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemRendererMixin.java deleted file mode 100644 index 79b2d1d3..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ItemRendererMixin.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; - -import net.minecraft.client.renderer.ItemModelShaper; -import net.minecraft.client.renderer.entity.ItemRenderer; -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.world.item.Item; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(ItemRenderer.class) -@ClientOnlyMixin -public class ItemRendererMixin { - /** - * Don't waste space putting all these locations into the cache, compute them on demand later. - */ - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ItemModelShaper;register(Lnet/minecraft/world/item/Item;Lnet/minecraft/client/resources/model/ModelResourceLocation;)V")) - private void skipDefaultRegistration(ItemModelShaper shaper, Item item, ModelResourceLocation mrl) { - - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/MinecraftMixin_ModelTicking.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/MinecraftMixin_ModelTicking.java deleted file mode 100644 index 32b22087..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/MinecraftMixin_ModelTicking.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.model.ModelManager; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.embeddedt.modernfix.duck.IExtendedModelManager; -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(Minecraft.class) -@ClientOnlyMixin -public abstract class MinecraftMixin_ModelTicking { - @Shadow public abstract ModelManager getModelManager(); - - @Inject(method = "tick", at = @At(value = "RETURN")) - private void tickModels(CallbackInfo ci) { - ((IExtendedModelManager)this.getModelManager()).mfix$tick(); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelBakerImplMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelBakerImplMixin.java deleted file mode 100644 index 9ef63719..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelBakerImplMixin.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; - -import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.Material; -import net.minecraft.client.resources.model.ModelBakery; -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.client.resources.model.ModelState; -import net.minecraft.client.resources.model.UnbakedModel; -import net.minecraft.resources.ResourceLocation; -import org.embeddedt.modernfix.ModernFix; -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; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; - -import java.util.function.Function; - -@Mixin(ModelBakery.ModelBakerImpl.class) -@ClientOnlyMixin -public abstract class ModelBakerImplMixin { - @Shadow public abstract UnbakedModel getModel(ResourceLocation location); - - @Shadow(aliases = {"this$0"}) @Final private ModelBakery field_40571; - @Unique - private int mfix$getDepth = 0; - - /** - * @author embeddedt - * @reason force parent resolution to happen before model gets baked - */ - @ModifyReturnValue(method = "getModel", at = @At("RETURN")) - private UnbakedModel resolveParents(UnbakedModel model) { - mfix$getDepth++; - if(mfix$getDepth == 1) { - try { - model.resolveParents(this::getModel); - } catch(Exception e) { - ModernFix.LOGGER.warn("Exception encountered resolving parents", e); - } - } - mfix$getDepth--; - return model; - } - - @WrapMethod(method = "bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;)Lnet/minecraft/client/resources/model/BakedModel;") - private BakedModel mfix$lockWhenBaking(ResourceLocation location, ModelState transform, Operation original) { - var lock = ((IExtendedModelBakery)this.field_40571).mfix$getLock(); - lock.lock(); - try { - return original.call(location, transform); - } finally { - lock.unlock(); - } - } - - /** - * @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; - } - - @WrapMethod(method = "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 mfix$lockWhenBaking(ResourceLocation location, ModelState transform, Function textureGetter, Operation original) { - var lock = ((IExtendedModelBakery)this.field_40571).mfix$getLock(); - lock.lock(); - try { - return original.call(location, transform, textureGetter); - } finally { - lock.unlock(); - } - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelBakeryMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelBakeryMixin.java deleted file mode 100644 index 26c554c3..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelBakeryMixin.java +++ /dev/null @@ -1,274 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; - -import com.llamalad7.mixinextras.injector.ModifyExpressionValue; -import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import net.minecraft.client.color.block.BlockColors; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.BlockModelRotation; -import net.minecraft.client.resources.model.BlockStateModelLoader; -import net.minecraft.client.resources.model.ModelBakery; -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.client.resources.model.UnbakedModel; -import net.minecraft.core.DefaultedRegistry; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.profiling.ProfilerFiller; -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.IBlockStateModelLoader; -import org.embeddedt.modernfix.duck.IExtendedModelBakery; -import org.embeddedt.modernfix.util.DynamicOverridableMap; -import org.embeddedt.modernfix.util.LRUMap; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -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.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.locks.ReentrantLock; - -@Mixin(ModelBakery.class) -@ClientOnlyMixin -public abstract class ModelBakeryMixin implements IExtendedModelBakery { - @Unique - private BlockStateModelLoader dynamicLoader; - - @Unique - private final ReentrantLock modelBakeryLock = new ReentrantLock(); - - @Unique - private ModelBakery.TextureGetter textureGetter; - - @Unique - private BakedModel bakedMissingModel; - - @Shadow abstract UnbakedModel getModel(ResourceLocation resourceLocation); - - @Shadow @Final private UnbakedModel missingModel; - - @Unique - private static final boolean DEBUG_MODEL_LOADS = Boolean.getBoolean("modernfix.debugDynamicModelLoading"); - - /** - * Bake a model using the provided texture getter and location. The model is stored in {@link ModelBakeryMixin#bakedTopLevelModels}. - */ - @Shadow(aliases = "lambda$bakeModels$6") protected abstract void method_61072(ModelBakery.TextureGetter getter, ModelResourceLocation location, UnbakedModel model); - - @Shadow @Mutable @Final private Map bakedTopLevelModels; - @Shadow @Mutable @Final public Map topLevelModels; - @Shadow @Mutable @Final private Map unbakedCache; - @Shadow @Mutable @Final public Map bakedCache; - - @Shadow protected abstract void loadItemModelAndDependencies(ResourceLocation resourceLocation); - - - @Shadow @Final public static ModelResourceLocation MISSING_MODEL_VARIANT; - - @Shadow protected abstract void registerModelAndLoadDependencies(ModelResourceLocation modelLocation, UnbakedModel model); - - private final Map mfix$emulatedBakedRegistry = new DynamicOverridableMap<>(ModelResourceLocation.class, this::loadBakedModelDynamic); - - @Override - public UnbakedModel mfix$loadUnbakedModelDynamic(ModelResourceLocation location) { - if(location.equals(MISSING_MODEL_VARIANT)) { - return missingModel; - } - modelBakeryLock.lock(); - try { - UnbakedModel existing = this.topLevelModels.get(location); - if (existing != null) { - return existing; - } - if(DEBUG_MODEL_LOADS) { - ModernFix.LOGGER.info("Loading model {}", location); - } - if(location.variant().equals("inventory")) { - this.loadItemModelAndDependencies(location.id()); - } else if (location.variant().equals("fabric_resource") || location.variant().equals("standalone")) { - UnbakedModel unbakedModel = this.getModel(location.id()); - this.registerModelAndLoadDependencies(location, unbakedModel); - } else { - ((IBlockStateModelLoader)dynamicLoader).loadSpecificBlock(location); - } - return this.topLevelModels.getOrDefault(location, this.missingModel); - } finally { - modelBakeryLock.unlock(); - } - } - - @WrapMethod(method = "getModel") - private UnbakedModel mfix$lockWhenGettingModel(ResourceLocation modelLocation, Operation original) { - modelBakeryLock.lock(); - try { - return original.call(modelLocation); - } finally { - modelBakeryLock.unlock(); - } - } - - @Override - public UnbakedModel mfix$getMissingModel() { - return missingModel; - } - - @Unique - private BakedModel loadBakedModelDynamic(ModelResourceLocation location) { - if(location.equals(MISSING_MODEL_VARIANT)) { - return bakedMissingModel; - } - BakedModel model; - modelBakeryLock.lock(); - try { - model = bakedTopLevelModels.get(location); - if(model == null) { - UnbakedModel prototype = mfix$loadUnbakedModelDynamic(location); - if(prototype == missingModel) { - model = bakedMissingModel; - } else { - prototype.resolveParents(this::getModel); - if(DEBUG_MODEL_LOADS) { - ModernFix.LOGGER.info("Baking model {}", location); - } - this.method_61072(this.textureGetter, location, prototype); - model = bakedTopLevelModels.remove(location); - if(model == null) { - ModernFix.LOGGER.error("Failed to load model " + location); - model = bakedMissingModel; - } - for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) { - try { - model = integration.onBakedModelLoad(location, prototype, model, BlockModelRotation.X0_Y0, (ModelBakery)(Object)this, this.textureGetter); - } catch (RuntimeException e) { - ModernFix.LOGGER.error("Exception encountered running dynamic resources integration", e); - } - } - } - } - } finally { - modelBakeryLock.unlock(); - } - return model; - } - - @ModifyExpressionValue(method = "", at = @At(value = "CONSTANT", args = "stringValue=missing_model")) - private String replaceBackingMaps(String original) { - this.unbakedCache = new LRUMap<>(this.unbakedCache); - this.bakedCache = new LRUMap<>(this.bakedCache); - this.topLevelModels = new LRUMap<>(this.topLevelModels); - this.bakedTopLevelModels = new LRUMap<>(this.bakedTopLevelModels); - return original; - } - - @WrapOperation(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/BlockStateModelLoader;loadAllBlockStates()V")) - private void noInitialBlockStateLoad(BlockStateModelLoader instance, Operation original) { - dynamicLoader = instance; - original.call(instance); - } - - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/DefaultedRegistry;keySet()Ljava/util/Set;")) - private Set skipLoadingItems(DefaultedRegistry instance) { - return Collections.emptySet(); - } - - - @Inject(method = "bakeModels", at = @At("HEAD")) - private void storeTextureGetterAndBakeMissing(ModelBakery.TextureGetter textureGetter, CallbackInfo ci) { - this.textureGetter = textureGetter; - this.method_61072(textureGetter, MISSING_MODEL_VARIANT, Objects.requireNonNull(this.topLevelModels.get(MISSING_MODEL_VARIANT))); - this.bakedMissingModel = this.bakedTopLevelModels.get(MISSING_MODEL_VARIANT); - } - - private boolean inInitialLoad = true; - - @Inject(method = "bakeModels", at = @At("RETURN")) - private void onInitialBakeFinish(ModelBakery.TextureGetter textureGetter, CallbackInfo ci) { - var permanentMRLs = new ObjectOpenHashSet<>(this.bakedTopLevelModels.keySet()); - ((LRUMap)this.bakedTopLevelModels).setPermanentEntries(permanentMRLs); - ModernFix.LOGGER.info("Dynamic model bakery initial baking finished, with {} permanent top level baked models", this.bakedTopLevelModels.size()); - } - - @Inject(method = "", at = @At("RETURN")) - private void onInitialLoadFinish(BlockColors blockColors, ProfilerFiller profilerFiller, Map map, Map map2, CallbackInfo ci) { - var permanentMRLs = new ObjectOpenHashSet<>(this.topLevelModels.keySet()); - ((LRUMap)this.topLevelModels).setPermanentEntries(permanentMRLs); - ModernFix.LOGGER.info("Dynamic model bakery loading finished, with {} permanent top level models", this.topLevelModels.size()); - } - - @Unique - private int tickCount; - - @Unique - private static final int MAXIMUM_CACHE_SIZE = 1000; - - private void runCleanup() { - try { - ((LRUMap)this.unbakedCache).dropEntriesToMeetSize(MAXIMUM_CACHE_SIZE); - } catch(RuntimeException e) { - throw new IllegalStateException("Exception dropping entries in unbaked cache", e); - } - try { - ((LRUMap)this.bakedCache).dropEntriesToMeetSize(MAXIMUM_CACHE_SIZE); - } catch(RuntimeException e) { - throw new IllegalStateException("Exception dropping entries in baked cache", e); - } - try { - ((LRUMap)this.topLevelModels).dropEntriesToMeetSize(MAXIMUM_CACHE_SIZE); - } catch(RuntimeException e) { - throw new IllegalStateException("Exception dropping entries in top level models", e); - } - try { - ((LRUMap)this.bakedTopLevelModels).dropEntriesToMeetSize(MAXIMUM_CACHE_SIZE); - } catch(RuntimeException e) { - throw new IllegalStateException("Exception dropping entries in baked top level models", e); - } - } - - @Override - public void mfix$finishLoading() { - inInitialLoad = false; - } - - @Override - public void mfix$tick() { - if(inInitialLoad) { - return; - } - tickCount++; - if((tickCount % 200) == 0) { - if(modelBakeryLock.tryLock()) { - try { - runCleanup(); - } finally { - modelBakeryLock.unlock(); - } - } - } - } - - /** - * @author embeddedt - * @reason We provide a fake baked registry to the rest of Minecraft, that dynamically loads models. - */ - @Overwrite - public Map getBakedTopLevelModels() { - return this.mfix$emulatedBakedRegistry; - } - - @Override - public ReentrantLock mfix$getLock() { - return this.modelBakeryLock; - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelManagerMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelManagerMixin.java deleted file mode 100644 index 72924a15..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ModelManagerMixin.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Maps; -import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.client.resources.model.AtlasSet; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.BlockStateModelLoader; -import net.minecraft.client.resources.model.ModelBakery; -import net.minecraft.client.resources.model.ModelManager; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.Resource; -import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.util.GsonHelper; -import net.minecraft.util.profiling.ProfilerFiller; -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.ModernFix; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.embeddedt.modernfix.duck.IExtendedModelBakery; -import org.embeddedt.modernfix.duck.IExtendedModelManager; -import org.embeddedt.modernfix.util.CacheUtil; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Coerce; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyArg; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.io.BufferedReader; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.Executor; -import java.util.function.Function; -import java.util.stream.Collectors; - -@Mixin(ModelManager.class) -@ClientOnlyMixin -public class ModelManagerMixin implements IExtendedModelManager { - @Shadow private Map bakedRegistry; - - @Unique - private Runnable tickHandler = () -> {}; - - @Inject(method = "", at = @At("RETURN")) - private void injectDummyBakedRegistry(CallbackInfo ci) { - if(this.bakedRegistry == null) { - this.bakedRegistry = new HashMap<>(); - } - } - - @ModifyArg(method = "loadBlockModels", at = @At(value = "INVOKE", target = "Ljava/util/concurrent/CompletableFuture;thenCompose(Ljava/util/function/Function;)Ljava/util/concurrent/CompletableFuture;", ordinal = 0), index = 0) - private static Function, ? extends CompletionStage>> deferBlockModelLoad(Function, ? extends CompletionStage>> fn, @Local(ordinal = 0, argsOnly = true) ResourceManager manager) { - return resourceMap -> { - var cache = CacheUtil.simpleCacheForLambda(location -> loadSingleBlockModel(manager, location), 100L); - return CompletableFuture.completedFuture(Maps.asMap(Set.copyOf(resourceMap.keySet()), location -> cache.getUnchecked(location))); - }; - } - - @Redirect(method = "reload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelManager;loadBlockStates(Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) - private CompletableFuture>> deferBlockStateLoad(ResourceManager manager, Executor executor) { - var cache = CacheUtil.>simpleCacheForLambda(location -> loadSingleBlockState(manager, location), 100L); - var blockStateKeys = Set.copyOf(BlockStateModelLoader.BLOCKSTATE_LISTER.listMatchingResourceStacks(manager).keySet()); - return CompletableFuture.completedFuture(Maps.asMap(blockStateKeys, location -> cache.getUnchecked(location))); - } - - @Redirect(method = "loadModels", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/StateDefinition;getPossibleStates()Lcom/google/common/collect/ImmutableList;")) - private ImmutableList skipCollection(StateDefinition definition) { - return ImmutableList.of(); - } - - private static BlockModel loadSingleBlockModel(ResourceManager manager, ResourceLocation location) { - return manager.getResource(location).map(resource -> { - try (BufferedReader reader = resource.openAsReader()) { - return BlockModel.fromStream(reader); - } catch(IOException e) { - ModernFix.LOGGER.error("Couldn't load model", e); - return null; - } - }).orElse(null); - } - - private List loadSingleBlockState(ResourceManager manager, ResourceLocation location) { - return manager.getResourceStack(location).stream().map(resource -> { - try (BufferedReader reader = resource.openAsReader()) { - return new BlockStateModelLoader.LoadedJson(resource.sourcePackId(), GsonHelper.parse(reader)); - } catch(IOException e) { - ModernFix.LOGGER.error("Couldn't load blockstate", e); - return null; - } - }).filter(Objects::nonNull).collect(Collectors.toList()); - } - - @Inject(method = "loadModels", at = @At("RETURN")) - private void storeTicker(ProfilerFiller profilerFiller, Map map, ModelBakery modelBakery, CallbackInfoReturnable cir) { - tickHandler = ((IExtendedModelBakery)modelBakery)::mfix$tick; - } - - @Inject(method = "apply", at = @At("RETURN")) - private void freezeBakery(@Coerce Object reloadState, ProfilerFiller profilerFiller, CallbackInfo ci, @Local(ordinal = 0) ModelBakery bakery) { - ((IExtendedModelBakery)bakery).mfix$finishLoading(); - } - - @Override - public void mfix$tick() { - tickHandler.run(); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ctm/CTMModelBakeryAccessor.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ctm/CTMModelBakeryAccessor.java deleted file mode 100644 index 5fad4788..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ctm/CTMModelBakeryAccessor.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.embeddedt.modernfix.common.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 mfix$getBakedCache(); -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ctm/TextureMetadataHandlerMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ctm/TextureMetadataHandlerMixin.java deleted file mode 100644 index bfd22142..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ctm/TextureMetadataHandlerMixin.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.embeddedt.modernfix.common.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 scrapedTextures; - - @Inject(method = "", 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 dependencies = new ArrayDeque<>(); - Set seenModels = new HashSet<>(); - dependencies.push(mrl.id()); - seenModels.add(mrl.id()); - boolean shouldWrap = false; - Set> 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 textures = Sets.newHashSet(scrapedTextures.get(dep)); - Collection 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, m -> spriteGetter.get(key, m), BlockModelRotation.X0_Y0); - } - } - } - } -} \ No newline at end of file diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ldlib/ClientProxyImplMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ldlib/ClientProxyImplMixin.java deleted file mode 100644 index 5c8c1609..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/ldlib/ClientProxyImplMixin.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources.ldlib; - -import com.lowdragmc.lowdraglib.LDLib; -import com.lowdragmc.lowdraglib.client.ClientProxy; -import com.lowdragmc.lowdraglib.client.model.custommodel.CustomBakedModel; -import com.lowdragmc.lowdraglib.client.model.custommodel.LDLMetadataSection; -import com.lowdragmc.lowdraglib.client.model.forge.LDLRendererModel; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.Material; -import net.minecraft.client.resources.model.ModelBakery; -import net.minecraft.client.resources.model.ModelResourceLocation; -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.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; - -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -@Mixin(ClientProxy.class) -@ClientOnlyMixin -@RequiresMod("ldlib") -public abstract class ClientProxyImplMixin implements ModernFixClientIntegration { - @Inject(method = "", at = @At("RETURN")) - private void registerIntegration(CallbackInfo ci) { - ModernFixClient.CLIENT_INTEGRATIONS.add(this); - } - - @Redirect(method = "modelBake", at = @At(value = "INVOKE", target = "Ljava/util/Map;entrySet()Ljava/util/Set;", ordinal = 0), remap = false) - private Set disableLoop(Map map) { - return Set.of(); - } - - @Override - public BakedModel onBakedModelLoad(ModelResourceLocation mrl, UnbakedModel rootModel, BakedModel baked, ModelState state, ModelBakery bakery, ModelBakery.TextureGetter textureGetter) { - if (baked == null) { - return null; - } - if (rootModel != null) { - if (baked instanceof LDLRendererModel) { - return baked; - } - if (baked.isCustomRenderer()) { // Nothing we can add to builtin models - return baked; - } - Deque dependencies = new ArrayDeque<>(); - Set seenModels = new HashSet<>(); - ResourceLocation rl = mrl.id(); - dependencies.push(rl); - seenModels.add(rl); - boolean shouldWrap = ClientProxy.WRAPPED_MODELS.getOrDefault(mrl, false); - // 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; - } - try { - Set textures = new HashSet<>(ClientProxy.SCRAPED_TEXTURES.get(dep)); - for (Material tex : textures) { - // Cache all dependent texture metadata - // At least one texture has CTM metadata, so we should wrap this baked - if (!LDLMetadataSection.getMetadata(LDLMetadataSection.spriteToAbsolute(tex.texture())).isMissing()) { // TODO lazy - shouldWrap = true; - break; - } - } - if (!shouldWrap) { - for (ResourceLocation newDep : model.getDependencies()) { - if (seenModels.add(newDep)) { - dependencies.push(newDep); - } - } - } - } catch (Exception e) { - LDLib.LOGGER.error("Error loading baked dependency {} for baked {}. Skipping...", dep, rl, e); - } - } - ClientProxy.WRAPPED_MODELS.put(mrl, shouldWrap); - if (shouldWrap) { - return new CustomBakedModel<>(baked); - } - } - return baked; - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_structure_manager/StructureManagerMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_structure_manager/StructureManagerMixin.java index c25d1380..7e613dc0 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_structure_manager/StructureManagerMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_structure_manager/StructureManagerMixin.java @@ -4,7 +4,7 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.mojang.datafixers.DataFixer; import net.minecraft.core.HolderGetter; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; @@ -24,12 +24,12 @@ import java.util.Optional; @Mixin(StructureTemplateManager.class) public class StructureManagerMixin { @Shadow @Final @Mutable - private Map> structureRepository; + private Map> structureRepository; @Inject(method = "", at = @At("RETURN")) private void makeStructuresSafe(ResourceManager arg, LevelStorageSource.LevelStorageAccess arg2, DataFixer dataFixer, HolderGetter arg3, CallbackInfo ci) { /* Structures needing to be reloaded is not a huge issue since we optimize loading them already */ - Cache> structureCache = CacheBuilder.newBuilder() + Cache> structureCache = CacheBuilder.newBuilder() .softValues() .build(); this.structureRepository = structureCache.asMap(); diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_ingredients/IngredientMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_ingredients/IngredientMixin.java deleted file mode 100644 index 0b619714..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_ingredients/IngredientMixin.java +++ /dev/null @@ -1,192 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.faster_ingredients; - -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntComparators; -import it.unimi.dsi.fastutil.ints.IntList; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.ItemStackLinkedSet; -import net.minecraft.world.item.crafting.Ingredient; -import net.neoforged.neoforge.common.crafting.ICustomIngredient; -import org.embeddedt.modernfix.neoforge.load.MinecraftServerReloadTracker; -import org.embeddedt.modernfix.neoforge.recipe.ExtendedIngredient; -import org.embeddedt.modernfix.neoforge.recipe.IngredientItemStacksSoftReference; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -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.ArrayList; -import java.util.stream.Collectors; - -@Mixin(value = Ingredient.class, priority = 700) -public abstract class IngredientMixin implements ExtendedIngredient { - @Shadow @Final - private Ingredient.Value[] values; - - @Shadow private @Nullable IntList stackingIds; - - @Shadow @Nullable private ItemStack[] itemStacks; - - @Shadow public abstract boolean isCustom(); - - @Shadow private ICustomIngredient customIngredient; - - @Unique - private boolean isVanilla() { - return !this.isCustom(); - } - - private volatile IngredientItemStacksSoftReference mfix$cachedItemStacks; - - /** - * Minecraft's server resource loading process has a design flaw in that tags are loaded, recipes are loaded, - * then tags are bound to the server registries. This results in recipe modification mods like KubeJS/CraftTweaker - * not being able to use Ingredient.test reliably as the TagValue will not find any contents for the given tag. - * To work around this issue these mods track tag context themselves and then patch TagValue.getItems to use it - * during the resource reload process. We often bypass Value.getItems, so we must disable that bypass - * whenever a server reload is in progress. - *

- * An alternative fix would be to bind tags ourselves when the recipe manager reload begins, before control is - * handed to these mods. However, it's unclear if there would be any negative side effects from binding tags early - * like this. Moreover, this fix would only work if the mod-provided patches to getItems read exactly what the - * registry would normally contain, rather than a modified version. - *

- * Note: this is a separate problem from the issue where clients may receive recipes before tags in 1.21. - */ - private boolean mfix$areTagsAvailable() { - return !MinecraftServerReloadTracker.isReloadActive(); - } - - /** - * @author embeddedt - * @reason tag ingredients can be tested without iterating over all items - */ - @Inject(method = "test(Lnet/minecraft/world/item/ItemStack;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/crafting/Ingredient;getItems()[Lnet/minecraft/world/item/ItemStack;"), cancellable = true) - private void modernfix$fasterTagIngredientTest(ItemStack stack, CallbackInfoReturnable cir) { - if (this.isVanilla() && this.values.length == 1 && this.values[0] instanceof Ingredient.TagValue tagValue && mfix$areTagsAvailable()) { - cir.setReturnValue(stack.getItemHolder().is(tagValue.tag())); - } - } - - /** - * @author embeddedt - * @reason exploding the stack list is unnecessary - */ - @Inject(method = "hasNoItems", at = @At("HEAD"), cancellable = true, remap = false) - public void hasNoItems(CallbackInfoReturnable cir) { - if (this.isVanilla()) { - cir.setReturnValue(!this.containsItems()); - } - } - - @Unique - private boolean isEmptyTagStack(ItemStack item) { - return item.getItem() == net.minecraft.world.item.Items.BARRIER && item.getHoverName() instanceof net.minecraft.network.chat.MutableComponent hoverName && hoverName.getString().startsWith("Empty Tag: "); - } - - @Unique - private boolean containsItems() { - for (Ingredient.Value value : this.values) { - if (value instanceof Ingredient.ItemValue) { - return true; - } else if (value instanceof Ingredient.TagValue tagValue && mfix$areTagsAvailable()) { - var holderSetOpt = BuiltInRegistries.ITEM.getTag(tagValue.tag()); - if (holderSetOpt.isPresent() && holderSetOpt.get().size() > 0) { - return true; - } - } else { - var items = value.getItems(); - if (items.isEmpty() || isEmptyTagStack(items.iterator().next())) { - // Doesn't have items - continue; - } - return true; - } - } - return false; - } - - /** - * @author embeddedt - * @reason tag ingredients can be converted to stacking IDs without expanding into stacks, since stacking only - * goes by item ID - */ - @Inject(method = "getStackingIds", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/crafting/Ingredient;getItems()[Lnet/minecraft/world/item/ItemStack;"), cancellable = true) - private void modernfix$fasterTagIngredientStacking(CallbackInfoReturnable cir) { - if (this.isVanilla() && this.values.length == 1 && this.values[0] instanceof Ingredient.TagValue tagValue && mfix$areTagsAvailable()) { - var tag = BuiltInRegistries.ITEM.getTag(tagValue.tag()); - if (!tag.isPresent() || tag.get().size() == 0) { - return; - } - var list = new IntArrayList(tag.get().stream().mapToInt(h -> BuiltInRegistries.ITEM.getId(h.value())).toArray()); - list.sort(IntComparators.NATURAL_COMPARATOR); - this.stackingIds = list; - cir.setReturnValue(list); - } - } - - /** - * @author embeddedt - * @reason Change caching of item stacks to use a soft reference, which allows the GC to evict the array under - * memory pressure/when it hasn't been used. - */ - @Overwrite - public ItemStack[] getItems() { - // For compatibility if mods explicitly force a set of item stacks to be used - if (this.itemStacks != null) { - return this.itemStacks; - } - if (this.customIngredient != null) { - // We probably have to cache this as mods won't make it fast if they expect Neo to cache it - this.itemStacks = this.customIngredient.getItems().collect(Collectors.toCollection(ItemStackLinkedSet::createTypeAndComponentsSet)).toArray(ItemStack[]::new); - return this.itemStacks; - } - var cache = this.mfix$cachedItemStacks; - if (cache != null) { - var stacks = cache.get(); - if (stacks != null) { - return stacks; - } - } - ItemStack[] result = computeItemsArray(); - this.mfix$cachedItemStacks = new IngredientItemStacksSoftReference((Ingredient)(Object)this, result); - return result; - } - - private ItemStack[] computeItemsArray() { - // Fast path for case with one item - if (this.values.length == 1) { - if (this.values[0] instanceof Ingredient.TagValue tagValue && mfix$areTagsAvailable()) { - var tag = BuiltInRegistries.ITEM.getTag(tagValue.tag()); - if (tag.isPresent() && tag.get().size() > 0) { - var holderSet = tag.get(); - ItemStack[] result = new ItemStack[holderSet.size()]; - for (int i = 0; i < result.length; i++) { - result[i] = new ItemStack(holderSet.get(i)); - } - return result; - } - } - } - ArrayList itemList = new ArrayList<>(2); - for (var value : this.values) { - var collection = value.getItems(); - itemList.ensureCapacity(collection.size() + itemList.size()); - for (var item : collection) { - itemList.add(item); - } - } - return itemList.toArray(ItemStack[]::new); - } - - @Override - public void mfix$clearReference() { - this.mfix$cachedItemStacks = null; - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/GameRendererMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/GameRendererMixin.java deleted file mode 100644 index 6c78fdd1..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/GameRendererMixin.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.faster_item_rendering; - -import net.minecraft.client.renderer.GameRenderer; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.embeddedt.modernfix.render.RenderState; -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.callback.CallbackInfo; - -@Mixin(GameRenderer.class) -@ClientOnlyMixin -public class GameRendererMixin { - @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;renderLevel(Lnet/minecraft/client/DeltaTracker;)V", shift = At.Shift.BEFORE)) - private void markRenderingLevel(CallbackInfo ci) { - RenderState.IS_RENDERING_LEVEL = true; - } - - @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;renderLevel(Lnet/minecraft/client/DeltaTracker;)V", shift = At.Shift.AFTER)) - private void markNotRenderingLevel(CallbackInfo ci) { - RenderState.IS_RENDERING_LEVEL = false; - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/ItemRendererMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/ItemRendererMixin.java deleted file mode 100644 index d138f29d..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_item_rendering/ItemRendererMixin.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.faster_item_rendering; - -import com.llamalad7.mixinextras.sugar.Local; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.block.model.ItemTransform; -import net.minecraft.client.renderer.entity.ItemRenderer; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.SimpleBakedModel; -import net.minecraft.world.item.ItemDisplayContext; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.embeddedt.modernfix.render.FastItemRenderType; -import org.embeddedt.modernfix.render.RenderState; -import org.embeddedt.modernfix.render.SimpleItemModelView; -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.ModifyArg; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(value = ItemRenderer.class, priority = 600) -@ClientOnlyMixin -public abstract class ItemRendererMixin { - private ItemDisplayContext transformType; - private final SimpleItemModelView modelView = new SimpleItemModelView(); - - @Inject(method = "render", at = @At("HEAD")) - private void markRenderingType(ItemStack itemStack, ItemDisplayContext transformType, boolean leftHand, PoseStack matrixStack, MultiBufferSource buffer, int combinedLight, int combinedOverlay, BakedModel model, CallbackInfo ci) { - this.transformType = transformType; - } - - /** - * If a model - * - is a vanilla item model (SimpleBakedModel), - * - has no custom GUI transforms, and - * - is being rendered in 2D on a GUI - * we do not need to go through the process of rendering every quad. Just render the south ones (the ones facing the - * camera). - */ - @ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/ItemRenderer;renderModelLists(Lnet/minecraft/client/resources/model/BakedModel;Lnet/minecraft/world/item/ItemStack;IILcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;)V"), index = 0) - private BakedModel useSimpleWrappedItemModel(BakedModel model, ItemStack stack, int combinedLight, int combinedOverlay, PoseStack matrixStack, VertexConsumer buffer, @Local(ordinal = 0) BakedModel originalModel) { - // Forge composite models split themselves into a smaller simple model, we need to detect that the parent - // was not simple - if(originalModel != null && originalModel.getClass() != SimpleBakedModel.class) { - return model; - } - - if(!RenderState.IS_RENDERING_LEVEL && !stack.isEmpty() && model.getClass() == SimpleBakedModel.class && transformType == ItemDisplayContext.GUI) { - FastItemRenderType type; - ItemTransform transform = model.getTransforms().gui; - if(transform == ItemTransform.NO_TRANSFORM) - type = FastItemRenderType.SIMPLE_ITEM; - else if(stack.getItem() instanceof BlockItem && isBlockTransforms(transform)) - type = FastItemRenderType.SIMPLE_BLOCK; - else - return model; - modelView.setItem(model); - modelView.setType(type); - return modelView; - } else - return model; - } - - private boolean isBlockTransforms(ItemTransform transform) { - return transform.rotation.x() == 30f - && transform.rotation.y() == 225f - && transform.rotation.z() == 0f; - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_texture_stitching/StitcherMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_texture_stitching/StitcherMixin.java deleted file mode 100644 index 228647f6..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/faster_texture_stitching/StitcherMixin.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.faster_texture_stitching; - -import com.google.common.collect.ImmutableList; -import com.mojang.datafixers.util.Pair; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import net.minecraft.client.renderer.texture.Stitcher; -import net.minecraft.client.renderer.texture.StitcherException; -import org.embeddedt.modernfix.ModernFix; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.embeddedt.modernfix.platform.ModernFixPlatformHooks; -import org.embeddedt.modernfix.textures.StbStitcher; -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 java.util.Comparator; -import java.util.List; -import java.util.stream.Stream; - -@Mixin(Stitcher.class) -@ClientOnlyMixin -public class StitcherMixin { - @Shadow @Final private List> texturesToBeStitched; - - @Shadow private int storageX; - - @Shadow private int storageY; - - @Shadow @Final private int maxWidth; - @Shadow @Final private int maxHeight; - - @Shadow @Final private static Comparator> HOLDER_COMPARATOR; - private List> loadableSpriteInfos; - - /** - * @author embeddedt, SuperCoder79 - * @reason Use improved STB stitcher instead of the vanilla implementation, for performance - */ - @Inject(method = "stitch", at = @At("HEAD"), cancellable = true) - private void stitchFast(CallbackInfo ci) { - this.loadableSpriteInfos = null; - if(!ModernFixPlatformHooks.INSTANCE.isLoadingNormally()) { - ModernFix.LOGGER.error("Using vanilla stitcher implementation due to invalid loading state"); - return; - } - if(this.texturesToBeStitched.size() < 100) { - // The vanilla implementation is fine for small atlases, and using it allows mods like JEI that depend on - // precise texture alignments to avoid bugs. - return; - } - ci.cancel(); - ObjectArrayList> holderList = new ObjectArrayList<>(this.texturesToBeStitched); - holderList.sort(HOLDER_COMPARATOR); - Stitcher.Holder[] aholder = holderList.toArray(new Stitcher.Holder[0]); - - Pair, List>> packingInfo = StbStitcher.packRects(aholder); - this.storageX = packingInfo.getFirst().getFirst(); - this.storageY = packingInfo.getFirst().getSecond(); - - // Detect an oversized atlas generated in the previous step. - if(this.storageX > this.maxWidth || this.storageY > this.maxHeight) { - ModernFix.LOGGER.error("Requested atlas size {}x{} exceeds maximum of {}x{}", this.storageX, this.storageY, this.maxWidth, this.maxHeight); - throw new StitcherException(aholder[0].entry(), Stream.of(aholder).map(arg -> arg.entry()).collect(ImmutableList.toImmutableList())); - } - - this.loadableSpriteInfos = packingInfo.getSecond(); - } - - /** - * @author embeddedt, SuperCoder79 - * @reason We setup the image ourselves in the StbStitcher, so we just feed this information back into the vanilla code - */ - @Inject(method = "gatherSprites", at = @At("HEAD"), cancellable = true) - private void gatherSpritesFast(Stitcher.SpriteLoader spriteLoader, CallbackInfo ci) { - if(this.loadableSpriteInfos == null) - return; - ci.cancel(); - for(StbStitcher.LoadableSpriteInfo info : loadableSpriteInfos) { - spriteLoader.load(info.info, info.x, info.y); - } - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/fix_loop_spin_waiting/MinecraftServerMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/fix_loop_spin_waiting/MinecraftServerMixin.java deleted file mode 100644 index b2257336..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/fix_loop_spin_waiting/MinecraftServerMixin.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.fix_loop_spin_waiting; - -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import net.minecraft.Util; -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.thread.BlockableEventLoop; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; - -import java.util.concurrent.locks.LockSupport; -import java.util.function.BooleanSupplier; - -@Mixin(value = MinecraftServer.class, priority = 500) -public abstract class MinecraftServerMixin extends BlockableEventLoop { - @Shadow private long nextTickTimeNanos; - - protected MinecraftServerMixin(String name) { - super(name); - } - - @Unique - private boolean mfix$isWaitingForNextTick = false; - - @WrapOperation( - method = "waitUntilNextTick", - at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;managedBlock(Ljava/util/function/BooleanSupplier;)V") - ) - private void managedBlock(MinecraftServer instance, BooleanSupplier isDone, Operation original) { - try { - this.mfix$isWaitingForNextTick = true; - original.call(instance, isDone); - } finally { - this.mfix$isWaitingForNextTick = false; - } - } - - @WrapOperation(method = "waitForTasks", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/thread/ReentrantBlockableEventLoop;waitForTasks()V")) - private void waitLongerForTasks(MinecraftServer instance, Operation original) { - if (this.mfix$isWaitingForNextTick) { - LockSupport.parkNanos("waiting for tasks", this.nextTickTimeNanos - Util.getNanos()); - } else { - original.call(instance); - } - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/ingredient_item_deduplication/IngredientItemValueMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/ingredient_item_deduplication/IngredientItemValueMixin.java deleted file mode 100644 index e214ca91..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/ingredient_item_deduplication/IngredientItemValueMixin.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.ingredient_item_deduplication; - -import com.llamalad7.mixinextras.injector.ModifyExpressionValue; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Ingredient; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; - -@Mixin(Ingredient.ItemValue.class) -public class IngredientItemValueMixin { - /** - * @author embeddedt - * @reason Defensively copy the item so that the deduplication is not visible to most mods (unless they introspect - * the item held within this object directly). This is necessary since some mods edit the returned stack. - */ - @ModifyExpressionValue(method = "getItems", at = @At(value = "FIELD", target = "Lnet/minecraft/world/item/crafting/Ingredient$ItemValue;item:Lnet/minecraft/world/item/ItemStack;")) - private ItemStack mfix$defensiveCopy(ItemStack original) { - return original.copy(); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/ingredient_item_deduplication/IngredientMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/ingredient_item_deduplication/IngredientMixin.java deleted file mode 100644 index b5b882f2..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/ingredient_item_deduplication/IngredientMixin.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.ingredient_item_deduplication; - -import net.minecraft.world.item.crafting.Ingredient; -import org.embeddedt.modernfix.neoforge.recipe.IngredientValueDeduplicator; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyVariable; - -import java.util.stream.Stream; - -@Mixin(Ingredient.class) -public class IngredientMixin { - @ModifyVariable(method = "(Ljava/util/stream/Stream;)V", at = @At("HEAD"), argsOnly = true, ordinal = 0) - private static Stream injectDeduplicationPass(Stream stream) { - return stream.map(IngredientValueDeduplicator::deduplicate); - } - - @ModifyVariable(method = "([Lnet/minecraft/world/item/crafting/Ingredient$Value;)V", at = @At("HEAD"), argsOnly = true, ordinal = 0) - private static Ingredient.Value[] injectDeduplicationPassArray(Ingredient.Value[] values) { - if (values.length == 0) { - return values; - } - Ingredient.Value[] newValues = new Ingredient.Value[values.length]; - for (int i = 0; i < values.length; i++) { - newValues[i] = IngredientValueDeduplicator.deduplicate(values[i]); - } - return newValues; - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/ingredient_item_deduplication/PatchedDataComponentMapAccessor.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/ingredient_item_deduplication/PatchedDataComponentMapAccessor.java deleted file mode 100644 index d6e4fee6..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/ingredient_item_deduplication/PatchedDataComponentMapAccessor.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.ingredient_item_deduplication; - -import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; -import net.minecraft.core.component.DataComponentMap; -import net.minecraft.core.component.DataComponentType; -import net.minecraft.core.component.PatchedDataComponentMap; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.Optional; - -@Mixin(PatchedDataComponentMap.class) -public interface PatchedDataComponentMapAccessor { - @Accessor("prototype") - DataComponentMap mfix$getPrototype(); - @Accessor("patch") - Reference2ObjectMap, Optional> mfix$getPatch(); -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/lazy_search_tree_registry/SessionSearchTreesMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/lazy_search_tree_registry/SessionSearchTreesMixin.java index 1eb93c3d..39a54ba8 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/lazy_search_tree_registry/SessionSearchTreesMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/lazy_search_tree_registry/SessionSearchTreesMixin.java @@ -22,7 +22,7 @@ public class SessionSearchTreesMixin { @Shadow private CompletableFuture> recipeSearch; private Supplier> mfix$deferredSearchTreeSupplier; - @ModifyArg(method = { "method_60367", "lambda$updateRecipes$8" }, at = @At(value = "INVOKE", target = "Ljava/util/concurrent/CompletableFuture;supplyAsync(Ljava/util/function/Supplier;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) + @ModifyArg(method = { "lambda$updateRecipes$9" }, at = @At(value = "INVOKE", target = "Ljava/util/concurrent/CompletableFuture;supplyAsync(Ljava/util/function/Supplier;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) private Supplier> mfix$deferProcessing(Supplier> supplier) { this.mfix$deferredSearchTreeSupplier = supplier; return SearchTree::empty; diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/BooleanPropertyMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/BooleanPropertyMixin.java deleted file mode 100644 index 11d6bd3a..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/BooleanPropertyMixin.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.model_optimizations; - -import com.google.common.collect.ImmutableSet; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(BooleanProperty.class) -public class BooleanPropertyMixin { - /** - * There is no point comparing the immutable sets in any two instances of this class, as they will always be - * the same. - */ - @Redirect(method = "equals", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/ImmutableSet;equals(Ljava/lang/Object;)Z", remap = false), remap = false) - private boolean skipEqualityCheck(ImmutableSet instance, Object object) { - return true; - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/MultiVariantMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/MultiVariantMixin.java deleted file mode 100644 index 9e762b0f..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/MultiVariantMixin.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.model_optimizations; - -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import net.minecraft.client.renderer.block.model.MultiVariant; -import net.minecraft.client.renderer.block.model.Variant; -import net.minecraft.client.resources.model.UnbakedModel; -import net.minecraft.resources.ResourceLocation; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.List; -import java.util.function.Function; - -@Mixin(value = MultiVariant.class, priority = 700) -@ClientOnlyMixin -public abstract class MultiVariantMixin { - @Shadow public abstract List getVariants(); - - /** - * @author embeddedt - * @reason avoid streams, try to optimize for common case - */ - @Overwrite - public void resolveParents(Function modelGetter) { - var variants = this.getVariants(); - // There is usually only a single variant - if (variants.size() == 1) { - modelGetter.apply(variants.get(0).getModelLocation()).resolveParents(modelGetter); - } else if(variants.size() > 1) { - ObjectOpenHashSet seenLocations = new ObjectOpenHashSet<>(variants.size()); - for (var variant : variants) { - var location = variant.getModelLocation(); - if (seenLocations.add(location)) { - modelGetter.apply(location).resolveParents(modelGetter); - } - } - } - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/SelectorMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/SelectorMixin.java deleted file mode 100644 index e4c818c7..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/SelectorMixin.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.model_optimizations; - -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.client.renderer.block.model.multipart.Selector; -import net.minecraft.world.level.block.state.StateDefinition; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -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.callback.CallbackInfoReturnable; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Predicate; - -@Mixin(Selector.class) -@ClientOnlyMixin -public class SelectorMixin { - private ConcurrentHashMap, Predicate> predicateCache = new ConcurrentHashMap<>(); - @Inject(method = "getPredicate", at = @At("HEAD"), cancellable = true) - private void useCachedPredicate(StateDefinition pState, CallbackInfoReturnable> cir) { - Predicate cached = this.predicateCache.get(pState); - if(cached != null) - cir.setReturnValue(cached); - } - - @Inject(method = "getPredicate", at = @At("RETURN")) - private void storeCachedPredicate(StateDefinition pState, CallbackInfoReturnable> cir) { - this.predicateCache.put(pState, cir.getReturnValue()); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/TransformationMatrixMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/TransformationMatrixMixin.java deleted file mode 100644 index d495ceb3..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/model_optimizations/TransformationMatrixMixin.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.model_optimizations; - -import com.mojang.math.Transformation; -import org.joml.Matrix4f; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Objects; - -@Mixin(Transformation.class) -@ClientOnlyMixin -public class TransformationMatrixMixin { - @Shadow @Final private Matrix4f matrix; - private Integer cachedHashCode = null; - /** - * @author embeddedt - * @reason use cached hashcode if exists - */ - @Overwrite(remap = false) - public int hashCode() { - int hash; - if(cachedHashCode != null) { - hash = cachedHashCode; - } else { - hash = Objects.hashCode(this.matrix); - cachedHashCode = hash; - } - return hash; - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/mojang_registry_size/StateHolderMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/mojang_registry_size/StateHolderMixin.java deleted file mode 100644 index 9e67dd7b..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/mojang_registry_size/StateHolderMixin.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.mojang_registry_size; - -import com.google.common.collect.ArrayTable; -import com.google.common.collect.HashBasedTable; -import com.google.common.collect.ImmutableTable; -import com.google.common.collect.Table; -import net.minecraft.world.level.block.state.StateHolder; -import net.minecraft.world.level.block.state.properties.Property; -import org.embeddedt.modernfix.annotation.RequiresMod; -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; - -/** - * Minor mixin to avoid duplicate empty neighbor tables, used when FerriteCore is not present. Won't be enabled in 99% of - * modded environments but is useful for testing in dev without dragging in Fabric API. - */ -@Mixin(StateHolder.class) -@RequiresMod("!ferritecore") -public class StateHolderMixin { - @Shadow private Table, Comparable, ?> neighbours; - - /* optimize the case where block has no properties */ - @Inject(method = "populateNeighbours", at = @At("RETURN"), require = 0) - private void replaceEmptyTable(CallbackInfo ci) { - if((this.neighbours instanceof ArrayTable || this.neighbours instanceof HashBasedTable) && this.neighbours.isEmpty()) - this.neighbours = ImmutableTable.of(); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/patchouli_deduplicate_books/ClientBookRegistryMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/patchouli_deduplicate_books/ClientBookRegistryMixin.java deleted file mode 100644 index 4ce8d174..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/patchouli_deduplicate_books/ClientBookRegistryMixin.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.patchouli_deduplicate_books; - -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.neoforged.fml.util.ObfuscationReflectionHelper; -import org.embeddedt.modernfix.ModernFix; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -import org.embeddedt.modernfix.annotation.RequiresMod; -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.callback.CallbackInfo; -import vazkii.patchouli.client.book.BookContents; -import vazkii.patchouli.client.book.BookEntry; -import vazkii.patchouli.client.book.BookPage; -import vazkii.patchouli.client.book.ClientBookRegistry; -import vazkii.patchouli.client.book.page.PageTemplate; -import vazkii.patchouli.client.book.template.BookTemplate; -import vazkii.patchouli.client.book.template.TemplateComponent; -import vazkii.patchouli.client.book.template.component.ComponentItemStack; -import vazkii.patchouli.common.book.Book; -import vazkii.patchouli.common.book.BookRegistry; - -import java.lang.reflect.Field; -import java.util.List; - -@Mixin(ClientBookRegistry.class) -@RequiresMod("patchouli") -@ClientOnlyMixin -public class ClientBookRegistryMixin { - @Inject(method = "reload", at = @At("RETURN"), remap = false) - private void performDeduplication(CallbackInfo ci) { - Field templateField = ObfuscationReflectionHelper.findField(PageTemplate.class, "template"); - Field contentsField = ObfuscationReflectionHelper.findField(Book.class, "contents"); - Field componentsField = ObfuscationReflectionHelper.findField(BookTemplate.class, "components"); - Field itemsField = ObfuscationReflectionHelper.findField(ComponentItemStack.class, "items"); - int numItemsCleared = 0; - for(Book book : BookRegistry.INSTANCE.books.values()) { - try { - BookContents contents = (BookContents)contentsField.get(book); - if(contents == null || contents.entries == null) - continue; - for(BookEntry entry : contents.entries.values()) { - for(BookPage page : entry.getPages()) { - if(page instanceof PageTemplate) { - List components; - BookTemplate template = (BookTemplate) templateField.get(page); - if(template == null) - continue; - components = (List) componentsField.get(template); - if(components == null) - continue; - for (TemplateComponent component : components) { - if (component instanceof ComponentItemStack) { - ItemStack[] items = (ItemStack[]) itemsField.get(component); - if(items == null) - continue; - for (int i = 0; i < items.length; i++) { - if (items[i] != null && items[i].getItem() == Items.AIR) { - numItemsCleared++; - items[i] = ItemStack.EMPTY; - } - } - } - } - } - } - } - } catch(ReflectiveOperationException ignored) { - } - } - ModernFix.LOGGER.info("Cleared {} unneeded book NBT tags", numItemsCleared); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockBehaviourInvoker.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockBehaviourInvoker.java deleted file mode 100644 index 9c9eb142..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockBehaviourInvoker.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.reduce_blockstate_cache_rebuilds; - -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.FluidState; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(BlockBehaviour.class) -public interface BlockBehaviourInvoker { - @Invoker - FluidState invokeGetFluidState(BlockState blockState); - @Invoker - boolean invokeIsRandomlyTicking(BlockState blockState); -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockCallbacksMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockCallbacksMixin.java deleted file mode 100644 index 0bb1276d..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockCallbacksMixin.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.embeddedt.modernfix.common.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 skipCache(StateDefinition 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 registry, CallbackInfo ci) { - BlockStateCacheHandler.invalidateCache(); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockStateBaseMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockStateBaseMixin.java deleted file mode 100644 index 42ba3cee..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockStateBaseMixin.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.reduce_blockstate_cache_rebuilds; - -import com.mojang.serialization.MapCodec; -import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateHolder; -import net.minecraft.world.level.block.state.properties.Property; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Fluids; -import org.embeddedt.modernfix.duck.IBlockState; -import org.objectweb.asm.Opcodes; -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.Redirect; - - - -@Mixin(BlockBehaviour.BlockStateBase.class) -public abstract class BlockStateBaseMixin extends StateHolder implements IBlockState { - protected BlockStateBaseMixin(Block object, Reference2ObjectArrayMap, Comparable> immutableMap, MapCodec mapCodec) { - super(object, immutableMap, mapCodec); - } - - private static final FluidState MFIX$VANILLA_DEFAULT_FLUID = Fluids.EMPTY.defaultFluidState(); - - @Shadow public abstract void initCache(); - - @Shadow private BlockBehaviour.BlockStateBase.Cache cache; - @Shadow private FluidState fluidState; - @Shadow private boolean isRandomlyTicking; - @Shadow @Deprecated private boolean legacySolid; - - @Shadow protected abstract BlockState asState(); - - private volatile boolean cacheInvalid = false; - private static boolean buildingCache = false; - @Override - public void clearCache() { - cacheInvalid = true; - } - - @Override - public boolean isCacheInvalid() { - return cacheInvalid; - } - - private void mfix$generateCache() { - if(cacheInvalid) { - // Ensure that only one block's cache is built at a time - synchronized (BlockBehaviour.BlockStateBase.class) { - if(cacheInvalid) { - // Ensure that if we end up in here recursively, we just use the original cache - if(!buildingCache) { - buildingCache = true; - try { - this.initCache(); - cacheInvalid = false; - } finally { - buildingCache = false; - } - } - } - - } - } - } - - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;cache:Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase$Cache;", - ordinal = 0 - )) - private BlockBehaviour.BlockStateBase.Cache dynamicCacheGen(BlockBehaviour.BlockStateBase base) { - mfix$generateCache(); - return this.cache; - } - - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;fluidState:Lnet/minecraft/world/level/material/FluidState;", - ordinal = 0 - ), require = 0) - private FluidState genCacheBeforeGettingFluid(BlockBehaviour.BlockStateBase base) { - // don't generate the full cache here as mods will iterate for the fluid state a lot - // assume blockstates will not change their contained fluidstate at runtime more than once - // this is how Lithium's implementation used to work, so it should be fine - if(this.cacheInvalid && this.fluidState == MFIX$VANILLA_DEFAULT_FLUID) { - synchronized (BlockBehaviour.BlockStateBase.class) { - if(!buildingCache) { - buildingCache = true; - try { - this.fluidState = ((BlockBehaviourInvoker)this.owner).invokeGetFluidState(this.asState()); - } finally { - buildingCache = false; - } - } - } - - } - return this.fluidState; - } - - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;isRandomlyTicking:Z", - ordinal = 0 - )) - private boolean genCacheBeforeGettingTicking(BlockBehaviour.BlockStateBase base) { - if(this.cacheInvalid) - return ((BlockBehaviourInvoker)this.owner).invokeIsRandomlyTicking(this.asState()); - return this.isRandomlyTicking; - } - - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;legacySolid:Z", - ordinal = 0 - )) - private boolean genCacheBeforeCheckingSolid(BlockBehaviour.BlockStateBase base) { - mfix$generateCache(); - return this.legacySolid; - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlocksMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlocksMixin.java deleted file mode 100644 index 3d35f9c3..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlocksMixin.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.reduce_blockstate_cache_rebuilds; - -import net.minecraft.world.item.Items; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import org.embeddedt.modernfix.blockstate.BlockStateCacheHandler; -import org.embeddedt.modernfix.duck.IBlockState; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyArg; -import org.spongepowered.asm.mixin.injection.Redirect; - -import java.util.function.Consumer; - -@Mixin(value = Blocks.class, priority = 1100) -public class BlocksMixin { - @ModifyArg(method = "rebuildCache", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/IdMapper;forEach(Ljava/util/function/Consumer;)V"), index = 0) - private static Consumer getEmptyConsumer(Consumer original) { - BlockStateCacheHandler.invalidateCache(); - return o -> {}; - } - - // require = 0 due to Forge removing the BLOCK_STATE_REGISTRY init here - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;initCache()V"), require = 0) - private static void skipCacheInit(BlockState state) { - // Trigger classloading of Items in case a mod expects it. - Items.AIR.asItem(); - // Mark the cache as invalid - ((IBlockState)state).clearCache(); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/remove_biome_temperature_cache/BiomeMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/remove_biome_temperature_cache/BiomeMixin.java deleted file mode 100644 index 0091ac98..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/remove_biome_temperature_cache/BiomeMixin.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.remove_biome_temperature_cache; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.biome.Biome; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -/* Idea from Lithium for 1.19.3 */ -@Mixin(Biome.class) -public abstract class BiomeMixin { - @Shadow protected abstract float getHeightAdjustedTemperature(BlockPos pos); - - /** - * @author 2No2Name - * @reason Remove caching, it's not effective - * @param pos - * @return - */ - @Overwrite - private float getTemperature(BlockPos pos) { - return this.getHeightAdjustedTemperature(pos); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/smart_ingredient_sync/ConnectionMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/smart_ingredient_sync/ConnectionMixin.java deleted file mode 100644 index 73bb298f..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/smart_ingredient_sync/ConnectionMixin.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.smart_ingredient_sync; - -import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import net.minecraft.network.Connection; -import net.minecraft.network.ConnectionProtocol; -import net.minecraft.network.PacketSendListener; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket; -import net.neoforged.neoforge.network.registration.NetworkRegistry; -import org.embeddedt.modernfix.neoforge.packet.SmartIngredientSyncPayload; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(Connection.class) -public class ConnectionMixin { - /** - * @author embeddedt - * @reason Provide context to the ingredient serializer about whether the enhanced sync protocol is supported. - */ - @WrapMethod(method = "doSendPacket") - private void modernfix$checkClientPresence(Packet packet, PacketSendListener sendListener, boolean flush, Operation original) { - if (packet instanceof ClientboundUpdateRecipesPacket && NetworkRegistry.hasChannel((Connection)(Object)this, ConnectionProtocol.PLAY, SmartIngredientSyncPayload.TYPE.id())) { - SmartIngredientSyncPayload.CLIENT_HAS_SMART_INGREDIENT_SYNC.set(true); - try { - original.call(packet, sendListener, flush); - } finally { - SmartIngredientSyncPayload.CLIENT_HAS_SMART_INGREDIENT_SYNC.set(false); - } - } else { - original.call(packet, sendListener, flush); - } - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/smart_ingredient_sync/IngredientMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/smart_ingredient_sync/IngredientMixin.java deleted file mode 100644 index 065c0e89..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/smart_ingredient_sync/IngredientMixin.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.smart_ingredient_sync; - -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.core.registries.Registries; -import net.minecraft.network.RegistryFriendlyByteBuf; -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.crafting.Ingredient; -import org.embeddedt.modernfix.neoforge.packet.SmartIngredientSyncPayload; -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.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(targets = {"net/minecraft/world/item/crafting/Ingredient$1"}) -public abstract class IngredientMixin { - - @Inject(method = "encode(Lnet/minecraft/network/RegistryFriendlyByteBuf;Lnet/minecraft/world/item/crafting/Ingredient;)V", - at = @At(value = "FIELD", target = "Lnet/minecraft/world/item/ItemStack;LIST_STREAM_CODEC:Lnet/minecraft/network/codec/StreamCodec;"), - cancellable = true) - private void checkForVanillaTagIngredient(RegistryFriendlyByteBuf buf, Ingredient ingredient, CallbackInfo ci) { - if (!SmartIngredientSyncPayload.CLIENT_HAS_SMART_INGREDIENT_SYNC.get() || ingredient.isCustom()) { - return; - } - Ingredient.Value[] values = ingredient.getValues(); - if (values.length == 1 && values[0] instanceof Ingredient.TagValue tagValue) { - var optionalHolderSet = BuiltInRegistries.ITEM.getTag(tagValue.tag()); - if (optionalHolderSet.isEmpty()) { - // Use default serialization logic for tags that do not exist - return; - } - - // Encode this as our tag ingredient type instead of using vanilla's flattening logic. - ci.cancel(); - buf.writeVarInt(-2); - buf.writeResourceLocation(tagValue.tag().location()); - } - } - - @Inject(method = "decode(Lnet/minecraft/network/RegistryFriendlyByteBuf;)Lnet/minecraft/world/item/crafting/Ingredient;", - at = @At(value = "HEAD"), - cancellable = true, remap = false) - private void decodeSmartIngredient(RegistryFriendlyByteBuf buf, CallbackInfoReturnable cir) { - int readerIndex = buf.readerIndex(); - var sizeId = buf.readVarInt(); - if (sizeId == -2) { - // Probably our ingredient - var tagKey = TagKey.create(Registries.ITEM, buf.readResourceLocation()); - cir.setReturnValue(Ingredient.of(tagKey)); - } else { - buf.readerIndex(readerIndex); - } - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/tag_id_caching/TagEntryMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/tag_id_caching/TagEntryMixin.java index f3e6cabe..d1a1c5b8 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/tag_id_caching/TagEntryMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/tag_id_caching/TagEntryMixin.java @@ -1,6 +1,6 @@ package org.embeddedt.modernfix.common.mixin.perf.tag_id_caching; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.tags.TagEntry; import net.minecraft.util.ExtraCodecs; import org.spongepowered.asm.mixin.Final; @@ -11,7 +11,7 @@ import org.spongepowered.asm.mixin.Shadow; @Mixin(TagEntry.class) public class TagEntryMixin { @Shadow @Final private boolean tag; - @Shadow @Final private ResourceLocation id; + @Shadow @Final private Identifier id; private ExtraCodecs.TagOrElementLocation cachedLoc; /** diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/tag_id_caching/TagOrElementLocationMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/tag_id_caching/TagOrElementLocationMixin.java index dcb7ee48..557af778 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/tag_id_caching/TagOrElementLocationMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/tag_id_caching/TagOrElementLocationMixin.java @@ -1,6 +1,6 @@ package org.embeddedt.modernfix.common.mixin.perf.tag_id_caching; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.util.ExtraCodecs; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.Shadow; @Mixin(ExtraCodecs.TagOrElementLocation.class) public class TagOrElementLocationMixin { @Shadow @Final private boolean tag; - @Shadow @Final private ResourceLocation id; + @Shadow @Final private Identifier id; private String cachedDecoratedId; /** diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/thread_priorities/IntegratedServerMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/thread_priorities/IntegratedServerMixin.java index 9cfe6466..df1c2d62 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/thread_priorities/IntegratedServerMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/thread_priorities/IntegratedServerMixin.java @@ -1,12 +1,7 @@ package org.embeddedt.modernfix.common.mixin.perf.thread_priorities; -import net.minecraft.client.Minecraft; -import net.minecraft.server.Services; -import net.minecraft.server.WorldStem; -import net.minecraft.server.packs.repository.PackRepository; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.client.server.IntegratedServer; -import net.minecraft.server.level.progress.ChunkProgressListenerFactory; -import net.minecraft.world.level.storage.LevelStorageSource; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -17,7 +12,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @ClientOnlyMixin public class IntegratedServerMixin { @Inject(method = "", at = @At("RETURN")) - private void adjustServerPriority(Thread thread, Minecraft arg, LevelStorageSource.LevelStorageAccess arg2, PackRepository arg3, WorldStem arg4, Services arg5, ChunkProgressListenerFactory arg6, CallbackInfo ci) { + private void adjustServerPriority(CallbackInfo ci, @Local(ordinal = 0, argsOnly = true) Thread thread) { int pri = 4; thread.setPriority(pri); } diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/thread_priorities/UtilMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/thread_priorities/UtilMixin.java index 71c7cb30..79b0c178 100644 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/thread_priorities/UtilMixin.java +++ b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/thread_priorities/UtilMixin.java @@ -1,6 +1,6 @@ package org.embeddedt.modernfix.common.mixin.perf.thread_priorities; -import net.minecraft.Util; +import net.minecraft.util.Util; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyArg; diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/MaterialRuleListMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/MaterialRuleListMixin.java deleted file mode 100644 index 83ba6cc1..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/MaterialRuleListMixin.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.perf.worldgen_allocation; - -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.DensityFunction; -import net.minecraft.world.level.levelgen.NoiseChunk; -import net.minecraft.world.level.levelgen.material.MaterialRuleList; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.List; - -@Mixin(value = MaterialRuleList.class, priority = 100) -public class MaterialRuleListMixin { - @Shadow @Final private List materialRuleList; - - /** - * @author embeddedt - * @reason Avoid iterator allocation - */ - @Overwrite - @Nullable - public BlockState calculate(DensityFunction.FunctionContext arg) { - BlockState state = null; - int s = this.materialRuleList.size(); - for(int i = 0; state == null && i < s; i++) { - NoiseChunk.BlockStateFiller blockStateFiller = this.materialRuleList.get(i); - state = blockStateFiller.calculate(arg); - } - return state; - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/safety/ItemColorsMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/safety/ItemColorsMixin.java deleted file mode 100644 index b213ecb3..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/safety/ItemColorsMixin.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.safety; - -import net.minecraft.client.color.item.ItemColors; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -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.callback.CallbackInfo; - -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -@Mixin(value = ItemColors.class, priority = 700) -@ClientOnlyMixin -public class ItemColorsMixin { - private Lock mapLock = new ReentrantLock(); - @Inject(method = "register", at = @At("HEAD")) - private void lockMapBeforeAccess(CallbackInfo ci) { - mapLock.lock(); - } - @Inject(method = "register", at = @At("TAIL")) - private void unlockMap(CallbackInfo ci) { - mapLock.unlock(); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/common/mixin/safety/ItemPropertiesMixin.java b/src/main/java/org/embeddedt/modernfix/common/mixin/safety/ItemPropertiesMixin.java deleted file mode 100644 index 883b5dab..00000000 --- a/src/main/java/org/embeddedt/modernfix/common/mixin/safety/ItemPropertiesMixin.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.embeddedt.modernfix.common.mixin.safety; - -import net.minecraft.client.renderer.item.ItemProperties; -import net.minecraft.client.renderer.item.ItemPropertyFunction; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import org.embeddedt.modernfix.annotation.ClientOnlyMixin; -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.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.Collections; -import java.util.Map; - -@Mixin(value = ItemProperties.class, priority = 700) -@ClientOnlyMixin -public class ItemPropertiesMixin { - @Shadow @Final @Mutable private static Map GENERIC_PROPERTIES; - @Shadow @Final @Mutable private static Map> PROPERTIES; - - @Inject(method = "", at = @At("RETURN")) - private static void useConcurrentMaps(CallbackInfo ci) { - GENERIC_PROPERTIES = Collections.synchronizedMap(GENERIC_PROPERTIES); - PROPERTIES = Collections.synchronizedMap(PROPERTIES); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/duck/IBlockStateModelLoader.java b/src/main/java/org/embeddedt/modernfix/duck/IBlockStateModelLoader.java deleted file mode 100644 index 87c96c66..00000000 --- a/src/main/java/org/embeddedt/modernfix/duck/IBlockStateModelLoader.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.embeddedt.modernfix.duck; - -import net.minecraft.client.resources.model.ModelResourceLocation; - -public interface IBlockStateModelLoader { - void loadSpecificBlock(ModelResourceLocation location); -} diff --git a/src/main/java/org/embeddedt/modernfix/duck/IExtendedModelBakery.java b/src/main/java/org/embeddedt/modernfix/duck/IExtendedModelBakery.java deleted file mode 100644 index c37c495d..00000000 --- a/src/main/java/org/embeddedt/modernfix/duck/IExtendedModelBakery.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.embeddedt.modernfix.duck; - -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.client.resources.model.UnbakedModel; - -import java.util.concurrent.locks.ReentrantLock; - -public interface IExtendedModelBakery { - void mfix$tick(); - void mfix$finishLoading(); - UnbakedModel mfix$loadUnbakedModelDynamic(ModelResourceLocation location); - UnbakedModel mfix$getMissingModel(); - ReentrantLock mfix$getLock(); -} diff --git a/src/main/java/org/embeddedt/modernfix/duck/IModelHoldingBlockState.java b/src/main/java/org/embeddedt/modernfix/duck/IModelHoldingBlockState.java index 0471e64c..6ec9cd49 100644 --- a/src/main/java/org/embeddedt/modernfix/duck/IModelHoldingBlockState.java +++ b/src/main/java/org/embeddedt/modernfix/duck/IModelHoldingBlockState.java @@ -1,8 +1,8 @@ package org.embeddedt.modernfix.duck; -import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.renderer.block.model.BlockStateModel; public interface IModelHoldingBlockState { - BakedModel mfix$getModel(); - void mfix$setModel(BakedModel model); + BlockStateModel mfix$getModel(); + void mfix$setModel(BlockStateModel model); } diff --git a/src/main/java/org/embeddedt/modernfix/duck/IServerLevel.java b/src/main/java/org/embeddedt/modernfix/duck/IServerLevel.java deleted file mode 100644 index 34c6b0c8..00000000 --- a/src/main/java/org/embeddedt/modernfix/duck/IServerLevel.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.embeddedt.modernfix.duck; - -import org.embeddedt.modernfix.world.StrongholdLocationCache; - -public interface IServerLevel { - StrongholdLocationCache mfix$getStrongholdCache(); -} diff --git a/src/main/java/org/embeddedt/modernfix/dynamicresources/DynamicModelCache.java b/src/main/java/org/embeddedt/modernfix/dynamicresources/DynamicModelCache.java deleted file mode 100644 index a2c90a9f..00000000 --- a/src/main/java/org/embeddedt/modernfix/dynamicresources/DynamicModelCache.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.embeddedt.modernfix.dynamicresources; - -import it.unimi.dsi.fastutil.Function; -import it.unimi.dsi.fastutil.objects.Reference2ReferenceLinkedOpenHashMap; -import net.minecraft.client.resources.model.BakedModel; - -import java.util.concurrent.locks.StampedLock; - -/** - * The Mojang Triple-based baked cache system is too slow to be hitting on every model retrieval, so - * we need a fast, concurrency-safe wrapper on top. - */ -public class DynamicModelCache { - private final Reference2ReferenceLinkedOpenHashMap cache = new Reference2ReferenceLinkedOpenHashMap<>(); - private final StampedLock lock = new StampedLock(); - private final Function modelRetriever; - private final boolean allowNulls; - - public DynamicModelCache(Function modelRetriever, boolean allowNulls) { - this.modelRetriever = modelRetriever; - this.allowNulls = allowNulls; - } - - public void clear() { - long stamp = lock.writeLock(); - try { - cache.clear(); - } finally { - lock.unlock(stamp); - } - } - - private boolean needToPopulate(K state) { - long stamp = lock.readLock(); - try { - return !cache.containsKey(state); - } finally { - lock.unlock(stamp); - } - } - - private BakedModel getModelFromCache(K state) { - long stamp = lock.readLock(); - try { - return cache.get(state); - } finally { - lock.unlock(stamp); - } - } - - private BakedModel cacheModel(K state) { - BakedModel model = modelRetriever.apply(state); - - // Lock and modify our local, faster cache - long stamp = lock.writeLock(); - - try { - cache.putAndMoveToFirst(state, model); - // TODO: choose less arbitrary number - if(cache.size() >= 1000) { - cache.removeLast(); - } - } finally { - lock.unlock(stamp); - } - - return model; - } - - public BakedModel get(K key) { - BakedModel model = getModelFromCache(key); - - if(model == null && (!allowNulls || needToPopulate(key))) { - model = cacheModel(key); - } - - return model; - } -} diff --git a/src/main/java/org/embeddedt/modernfix/dynamicresources/DynamicModelProvider.java b/src/main/java/org/embeddedt/modernfix/dynamicresources/DynamicModelProvider.java deleted file mode 100644 index 67bd354c..00000000 --- a/src/main/java/org/embeddedt/modernfix/dynamicresources/DynamicModelProvider.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.embeddedt.modernfix.dynamicresources; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import net.minecraft.client.resources.model.UnbakedModel; -import net.minecraft.resources.ResourceLocation; - -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; - -/** - * Handles loading models dynamically, rather than at startup time. - */ -public class DynamicModelProvider { - private final Map internalModels; - private final Cache> loadedModels = - CacheBuilder.newBuilder() - .expireAfterAccess(3, TimeUnit.MINUTES) - .maximumSize(1000) - .concurrencyLevel(8) - .softValues() - .build(); - - public DynamicModelProvider(Map initialModels) { - this.internalModels = initialModels; - } - - public UnbakedModel getModel(ResourceLocation location) { - try { - return loadedModels.get(location, () -> Optional.ofNullable(loadModel(location))).orElse(null); - } catch(ExecutionException e) { - throw new RuntimeException(e.getCause()); - } - } - - private UnbakedModel loadModel(ResourceLocation location) { - return null; /* TODO :) */ - } -} diff --git a/src/main/java/org/embeddedt/modernfix/dynamicresources/DynamicSoundHelpers.java b/src/main/java/org/embeddedt/modernfix/dynamicresources/DynamicSoundHelpers.java deleted file mode 100644 index 32c1df83..00000000 --- a/src/main/java/org/embeddedt/modernfix/dynamicresources/DynamicSoundHelpers.java +++ /dev/null @@ -1,142 +0,0 @@ -package org.embeddedt.modernfix.dynamicresources; - -import com.mojang.blaze3d.audio.SoundBuffer; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; -import net.minecraft.resources.ResourceLocation; -import org.embeddedt.modernfix.ModernFix; -import org.jetbrains.annotations.NotNull; - -import java.util.AbstractMap; -import java.util.AbstractSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; - -public class DynamicSoundHelpers { - private static final long SOUND_EVICTION_DELAY = TimeUnit.SECONDS.toNanos(30); - private static final boolean debugDynamicSoundLoading = Boolean.getBoolean("modernfix.debugDynamicSoundLoading"); - - public interface SoundBufAccess { - long mfix$getDurationNanos(); - } - - public static final class Cache extends AbstractMap> { - private static class Entry { - private final CompletableFuture buffer; - private long lastAccessTime; - - private Entry(CompletableFuture buffer) { - this.buffer = buffer; - this.lastAccessTime = System.nanoTime(); - } - - public CompletableFuture getBuffer() { - this.lastAccessTime = System.nanoTime(); - return this.buffer; - } - - public long getDuration() { - var buf = this.buffer.getNow(null); - if (buf == null) { - return 0; - } - return ((SoundBufAccess)buf).mfix$getDurationNanos(); - } - - public boolean isExpired(long currentTs) { - long duration = getDuration(); - return duration > 0 && (currentTs - this.lastAccessTime) >= (duration + SOUND_EVICTION_DELAY); - } - - public void discard() { - this.buffer.thenAccept(SoundBuffer::discardAlBuffer); - } - - @Override - public String toString() { - return super.toString(); - } - } - - private final Object2ObjectLinkedOpenHashMap store = new Object2ObjectLinkedOpenHashMap<>(); - - public Cache(Map> otherMap) { - this.putAll(otherMap); - } - - private void checkExpired() { - long ts = System.nanoTime(); - var iter = this.store.object2ObjectEntrySet().fastIterator(); - while (iter.hasNext()) { - var entry = iter.next(); - if (entry.getValue().isExpired(ts)) { - if (debugDynamicSoundLoading) { - ModernFix.LOGGER.warn("Evicted sound {} with duration {} ms", entry.getKey(), entry.getValue().getDuration() / 1000000); - } - entry.getValue().discard(); - iter.remove(); - } else { - break; - } - } - } - - @Override - public CompletableFuture get(Object key) { - if (key instanceof ResourceLocation rl) { - var entry = this.store.getAndMoveToLast(rl); - CompletableFuture result = entry != null ? entry.getBuffer() : null; - this.checkExpired(); - return result; - } else { - return null; - } - } - - @Override - public CompletableFuture put(ResourceLocation key, CompletableFuture value) { - var entry = new Entry(value); - if (debugDynamicSoundLoading) { - ModernFix.LOGGER.info("Loaded sound {}", key); - } - var previousEntry = this.store.putAndMoveToLast(key, entry); - return previousEntry != null ? previousEntry.getBuffer() : null; - } - - @Override - public @NotNull Set>> entrySet() { - return new EntrySet(); - } - - private class EntrySet extends AbstractSet>> { - @Override - public Iterator>> iterator() { - var storeIter = store.entrySet().iterator(); - return new Iterator<>() { - @Override - public boolean hasNext() { - return storeIter.hasNext(); - } - - @Override - public Map.Entry> next() { - var entry = storeIter.next(); - return new AbstractMap.SimpleImmutableEntry<>(entry.getKey(), entry.getValue().buffer); - } - }; - } - - @Override - public int size() { - return store.size(); - } - - @Override - public void clear() { - store.clear(); - } - } - } -} diff --git a/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java b/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java deleted file mode 100644 index ec0962fd..00000000 --- a/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java +++ /dev/null @@ -1,107 +0,0 @@ -package org.embeddedt.modernfix.dynamicresources; - -import com.google.common.base.Splitter; -import com.google.common.collect.ImmutableList; -import net.minecraft.client.resources.model.*; -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 java.util.*; - -public class ModelBakeryHelpers { - /** - * The maximum number of baked models kept in memory at once. - */ - public static final int MAX_BAKED_MODEL_COUNT = 10000; - /** - * The maximum number of unbaked models kept in memory at once. - */ - public static final int MAX_UNBAKED_MODEL_COUNT = 10000; - /** - * The time in seconds after which a model becomes eligible for eviction if not used. - */ - public static final int MAX_MODEL_LIFETIME_SECS = 300; - - /** - * These folders will have all textures stitched onto the atlas when dynamic resources is enabled. - */ - public static String[] getExtraTextureFolders() { - return new String[] { - "attachment", - "bettergrass", - "block", - "blocks", - "cape", - "entity/bed", - "entity/chest", - "item", - "items", - "model", - "models", - "part", - "pipe", - "ropebridge", - "runes", - "solid_block", - "spell_effect", - "spell_projectile" - }; - } - - private static , V extends T> BlockState setPropertyGeneric(BlockState state, Property prop, Object o) { - return state.setValue(prop, (V)o); - } - - private static > T getValueHelper(Property property, String value) { - return property.getValue(value).orElse(null); - } - - private static final Splitter COMMA_SPLITTER = Splitter.on(','); - private static final Splitter EQUAL_SPLITTER = Splitter.on('=').limit(2); - - public static ImmutableList getBlockStatesForMRL(StateDefinition stateDefinition, ModelResourceLocation location) { - if(Objects.equals(location.getVariant(), "inventory")) - return ImmutableList.of(); - Set> fixedProperties = new HashSet<>(); - BlockState fixedState = stateDefinition.any(); - for(String s : COMMA_SPLITTER.split(location.getVariant())) { - Iterator iterator = EQUAL_SPLITTER.split(s).iterator(); - if (iterator.hasNext()) { - String s1 = iterator.next(); - Property property = stateDefinition.getProperty(s1); - if (property != null && iterator.hasNext()) { - String s2 = iterator.next(); - Object value = getValueHelper(property, s2); - if (value == null) { - throw new RuntimeException("Unknown value: '" + s2 + "' for blockstate property: '" + s1 + "' " + property.getPossibleValues()); - } - fixedState = setPropertyGeneric(fixedState, property, value); - fixedProperties.add(property); - } else if (!s1.isEmpty()) { - throw new RuntimeException("Unknown blockstate property: '" + s1 + "'"); - } - } - } - // check if there is only one possible state - if(fixedProperties.size() == stateDefinition.getProperties().size()) { - return ImmutableList.of(fixedState); - } - // generate all possible blockstates from the remaining properties - ArrayList> anyProperties = new ArrayList<>(stateDefinition.getProperties()); - anyProperties.removeAll(fixedProperties); - ArrayList finalList = new ArrayList<>(); - finalList.add(fixedState); - for(Property property : anyProperties) { - ArrayList newPermutations = new ArrayList<>(); - for(BlockState state : finalList) { - for(Comparable value : property.getPossibleValues()) { - newPermutations.add(setPropertyGeneric(state, property, value)); - } - } - finalList = newPermutations; - } - return ImmutableList.copyOf(finalList); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelLocationCache.java b/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelLocationCache.java deleted file mode 100644 index 6b0a1d45..00000000 --- a/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelLocationCache.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.embeddedt.modernfix.dynamicresources; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import net.minecraft.client.renderer.block.BlockModelShaper; -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.block.state.BlockState; - -import java.util.concurrent.ExecutionException; - -public class ModelLocationCache { - private static final LoadingCache blockLocationCache = CacheBuilder.newBuilder() - .maximumSize(10000) - .build(new CacheLoader() { - @Override - public ModelResourceLocation load(BlockState key) throws Exception { - return BlockModelShaper.stateToModelLocation(key); - } - }); - - private static final LoadingCache itemLocationCache = CacheBuilder.newBuilder() - .maximumSize(10000) - .build(new CacheLoader() { - @Override - public ModelResourceLocation load(Item key) throws Exception { - return new ModelResourceLocation(BuiltInRegistries.ITEM.getKey(key), "inventory"); - } - }); - - public static ModelResourceLocation get(BlockState state) { - if(state == null) - return null; - try { - return blockLocationCache.get(state); - } catch(ExecutionException e) { - throw new RuntimeException(e.getCause()); - } - } - - public static ModelResourceLocation get(Item item) { - if(item == null) - return null; - try { - return itemLocationCache.get(item); - } catch(ExecutionException e) { - throw new RuntimeException(e.getCause()); - } - } -} diff --git a/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelMissingException.java b/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelMissingException.java deleted file mode 100644 index a8a881b7..00000000 --- a/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelMissingException.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.embeddedt.modernfix.dynamicresources; - -public class ModelMissingException extends RuntimeException { - -} diff --git a/src/main/java/org/embeddedt/modernfix/neoforge/ModernFixConfig.java b/src/main/java/org/embeddedt/modernfix/neoforge/ModernFixConfig.java deleted file mode 100644 index cff21c7e..00000000 --- a/src/main/java/org/embeddedt/modernfix/neoforge/ModernFixConfig.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.embeddedt.modernfix.neoforge; - -import com.google.common.collect.ImmutableList; -import net.minecraft.resources.ResourceLocation; -import net.neoforged.neoforge.common.ModConfigSpec; - -import java.util.List; -import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -public class ModernFixConfig { - private static final ModConfigSpec.Builder COMMON_BUILDER = new ModConfigSpec.Builder(); - public static ModConfigSpec COMMON_CONFIG; - - public static ModConfigSpec.ConfigValue> BLACKLIST_ASYNC_JEI_PLUGINS; - - private static Set jeiPluginBlacklist; - - static { - Predicate locationValidator = o -> o instanceof String && ((String)o).contains(":"); - BLACKLIST_ASYNC_JEI_PLUGINS = COMMON_BUILDER - .comment("These JEI plugins will be loaded on the main thread") - .defineList("blacklist_async_jei_plugins", ImmutableList.of( - "jepb:jei_plugin" - ), locationValidator); - } - - static { - COMMON_CONFIG = COMMON_BUILDER.build(); - } - - public static Set getJeiPluginBlacklist() { - if(jeiPluginBlacklist == null) { - jeiPluginBlacklist = BLACKLIST_ASYNC_JEI_PLUGINS.get().stream().map(ResourceLocation::parse).collect(Collectors.toSet()); - } - return jeiPluginBlacklist; - } -} diff --git a/src/main/java/org/embeddedt/modernfix/neoforge/dynresources/IModelBakerImpl.java b/src/main/java/org/embeddedt/modernfix/neoforge/dynresources/IModelBakerImpl.java deleted file mode 100644 index 0de3e12f..00000000 --- a/src/main/java/org/embeddedt/modernfix/neoforge/dynresources/IModelBakerImpl.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.embeddedt.modernfix.neoforge.dynresources; - -public interface IModelBakerImpl { - void mfix$ignoreCache(); -} diff --git a/src/main/java/org/embeddedt/modernfix/neoforge/dynresources/ModelBakeEventHelper.java b/src/main/java/org/embeddedt/modernfix/neoforge/dynresources/ModelBakeEventHelper.java deleted file mode 100644 index c2175e10..00000000 --- a/src/main/java/org/embeddedt/modernfix/neoforge/dynresources/ModelBakeEventHelper.java +++ /dev/null @@ -1,337 +0,0 @@ -package org.embeddedt.modernfix.neoforge.dynresources; - -import com.google.common.collect.ForwardingMap; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Sets; -import com.google.common.graph.GraphBuilder; -import com.google.common.graph.MutableGraph; -import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.ModelBakery; -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.FileToIdConverter; -import net.neoforged.fml.ModContainer; -import net.neoforged.fml.ModList; -import net.neoforged.neoforgespi.language.IModInfo; -import org.embeddedt.modernfix.ModernFix; -import org.embeddedt.modernfix.util.ForwardingInclDefaultsMap; -import org.jetbrains.annotations.Nullable; - -import java.util.AbstractSet; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.function.BiFunction; - -/** - * Stores a list of all known default block/item models in the game, and provides a namespaced version - * of the model registry that emulates vanilla keySet behavior. - */ -public class ModelBakeEventHelper { - - private enum UniverseVisibility { - /** - * Mod cannot see any view of the universe of model locations. - */ - NONE, - /** - * Mod can see its own model locations and those of dependencies/dependents. - */ - SELF_AND_DEPS, - /** - * Mod can see every model location. - */ - EVERYTHING - } - private static final Map MOD_VISIBILITY_CONFIGURATION = ImmutableMap.builder() - .put("eternal_starlight", UniverseVisibility.SELF_AND_DEPS) // needed as a mitigation until https://github.com/LeoMinecraftModding/eternal-starlight/pull/82 is merged - .put("alexscaves", UniverseVisibility.SELF_AND_DEPS) - .put("refinedstorage", UniverseVisibility.SELF_AND_DEPS) - .put("cabletiers", UniverseVisibility.SELF_AND_DEPS) - .build(); - private final Map modelRegistry; - private final Set topLevelModelLocations; - - private final Set namespacesWithModels; - private final MutableGraph dependencyGraph; - - public ModelBakeEventHelper(Map modelRegistry) { - this.modelRegistry = modelRegistry; - int blockStateCount = 0; - for (var b : BuiltInRegistries.BLOCK) { - blockStateCount += b.getStateDefinition().getPossibleStates().size(); - } - this.topLevelModelLocations = new ObjectLinkedOpenHashSet<>(blockStateCount + BuiltInRegistries.ITEM.size()); - this.namespacesWithModels = new ObjectOpenHashSet<>(ModList.get().size()); - var modelLocationBuilder = new ModelLocationBuilder(); - BuiltInRegistries.BLOCK.entrySet().forEach(entry -> { - var location = entry.getKey().location(); - modelLocationBuilder.generateForBlock(topLevelModelLocations, entry.getValue(), location); - namespacesWithModels.add(location.getNamespace()); - }); - BuiltInRegistries.ITEM.keySet().forEach(key -> { - topLevelModelLocations.add(new ModelResourceLocation(key, "inventory")); - namespacesWithModels.add(key.getNamespace()); - }); - this.topLevelModelLocations.addAll(modelRegistry.keySet()); - // We add all standard item model locations here so that mods like JAOPCA that assume their remapping logic - // triggers loading of them (which it doesn't with dynamic resources on), will still detect the presence - // of their extra models in the emulated registry. - var itemModelLister = FileToIdConverter.json("models/item"); - itemModelLister.listMatchingResources(Minecraft.getInstance().getResourceManager()).keySet().forEach(itemModel -> { - this.topLevelModelLocations.add(ModelResourceLocation.inventory(itemModelLister.fileToId(itemModel))); - this.namespacesWithModels.add(itemModel.getNamespace()); - }); - for (var loc : modelRegistry.keySet()) { - this.namespacesWithModels.add(loc.id().getNamespace()); - } - this.dependencyGraph = buildDependencyGraph(); - } - - private MutableGraph buildDependencyGraph() { - MutableGraph dependencyGraph = GraphBuilder.undirected().build(); - ModList.get().forEachModContainer((id, mc) -> { - dependencyGraph.addNode(id); - for(IModInfo.ModVersion version : mc.getModInfo().getDependencies()) { - dependencyGraph.addNode(version.getModId()); - } - }); - for(String id : dependencyGraph.nodes()) { - Optional mContainer = ModList.get().getModContainerById(id); - if(mContainer.isPresent()) { - for(IModInfo.ModVersion version : mContainer.get().getModInfo().getDependencies()) { - // avoid self-loops - if(!Objects.equals(id, version.getModId()) && !version.getModId().equals("minecraft") && namespacesWithModels.contains(version.getModId())) - dependencyGraph.putEdge(id, version.getModId()); - } - } - } - return dependencyGraph; - } - - private static final Set WARNED_MOD_IDS = new HashSet<>(); - - /** - * Create a model registry that warns if keySet, entrySet, values are accessed. - * @param modId the mod that the event is being fired for - * @return a wrapper around the model registry - */ - private Map createWarningRegistry(String modId) { - return new ForwardingInclDefaultsMap() { - @Override - protected Map delegate() { - return modelRegistry; - } - - private void logWarning() { - if(!WARNED_MOD_IDS.add(modId)) - return; - ModernFix.LOGGER.warn("Mod '{}' is accessing Map#keySet/entrySet/values/replaceAll on the model registry map inside its event handler." + - " This probably won't work as expected with dynamic resources on. Prefer using Map#get/put and constructing ModelResourceLocations another way.", modId); - } - - @Override - public Set keySet() { - logWarning(); - return super.keySet(); - } - - @Override - public Set> entrySet() { - logWarning(); - return super.entrySet(); - } - - @Override - public Collection values() { - logWarning(); - return super.values(); - } - - @Override - public void replaceAll(BiFunction function) { - logWarning(); - super.replaceAll(function); - } - }; - } - - private Set computeVisibleModIds(String modId) { - Set deps; - try { - deps = this.dependencyGraph.adjacentNodes(modId); - } catch (IllegalArgumentException e) { - deps = Set.of(); - } - if (deps.isEmpty()) { - // avoid extra work below - return Set.of(modId); - } - var set = new ObjectOpenHashSet(); - set.add(modId); - set.addAll(deps); - return Set.copyOf(set); - } - - public Map wrapRegistry(String modId) { - var config = MOD_VISIBILITY_CONFIGURATION.getOrDefault(modId, UniverseVisibility.EVERYTHING); - if (config == UniverseVisibility.NONE) { - return createWarningRegistry(modId); - } - final Set modIdsToInclude = computeVisibleModIds(modId); - Set ourModelLocations; - if (config == UniverseVisibility.SELF_AND_DEPS) { - ModernFix.LOGGER.debug("Mod {} is restricted to seeing models from mods: [{}]", modId, String.join(", ", modIdsToInclude)); - ourModelLocations = Sets.filter(this.topLevelModelLocations, loc -> modIdsToInclude.contains(loc.id().getNamespace())); - } else { - ourModelLocations = this.topLevelModelLocations; - } - BakedModel missingModel = modelRegistry.get(ModelBakery.MISSING_MODEL_LOCATION); - return new EmulatedModelRegistry(modId, modIdsToInclude, missingModel, ourModelLocations); - } - - public class EmulatedModelRegistry extends ForwardingMap { - private final Set modIdsToInclude; - private final BakedModel missingModel; - private final Set ourModelLocations; - private final String modId; - - private EmulatedModelRegistry(String modId, Set modIdsToInclude, BakedModel missingModel, Set ourModelLocations) { - this.modId = modId; - this.modIdsToInclude = modIdsToInclude; - this.missingModel = missingModel; - this.ourModelLocations = ourModelLocations; - } - - @Override - protected Map delegate() { - return modelRegistry; - } - - @Override - public BakedModel get(@Nullable Object key) { - BakedModel model = super.get(key); - if(model == null && key instanceof ModelResourceLocation mrl && modIdsToInclude.contains(mrl.id().getNamespace())) { - ModernFix.LOGGER.warn("Model {} is missing, but was requested in model bake event. Returning missing model", key); - return missingModel; - } - return model; - } - - @Override - public Set keySet() { - return Collections.unmodifiableSet(ourModelLocations); - } - - @Override - public boolean containsKey(@Nullable Object key) { - return ourModelLocations.contains(key) || super.containsKey(key); - } - - @Override - public Set> entrySet() { - return new DynamicModelEntrySet(this, ourModelLocations); - } - - @Override - public void replaceAll(BiFunction 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); - for(ModelResourceLocation location : ourModelLocations) { - /* - * 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 - * it actually cares about the given model. - */ - boolean needsReplacement; - try { - needsReplacement = function.apply(location, null) != null; - } catch(Throwable e) { - needsReplacement = true; - } - if(needsReplacement) { - BakedModel existing = get(location); - BakedModel replacement = function.apply(location, existing); - if(replacement != existing) { - put(location, replacement); - } - } - } - } - } - - private static class DynamicModelEntrySet extends AbstractSet> { - private final Map modelRegistry; - private final Set modelLocations; - - private DynamicModelEntrySet(Map modelRegistry, Set modelLocations) { - this.modelRegistry = modelRegistry; - this.modelLocations = modelLocations; - } - - @Override - public Iterator> iterator() { - var iter = this.modelLocations.iterator(); - return new Iterator<>() { - @Override - public boolean hasNext() { - return iter.hasNext(); - } - - @Override - public Map.Entry next() { - return new DynamicModelEntry(iter.next()); - } - }; - } - - @Override - public boolean contains(Object o) { - if(o instanceof Map.Entry entry) { - return modelRegistry.containsKey(entry.getKey()); - } else { - return false; - } - } - - @Override - public int size() { - return modelRegistry.size(); - } - - @Override - public boolean removeAll(Collection c) { - throw new UnsupportedOperationException(); - } - - private class DynamicModelEntry implements Map.Entry { - private final ModelResourceLocation location; - - private DynamicModelEntry(ModelResourceLocation location) { - this.location = location; - } - - @Override - public ModelResourceLocation getKey() { - return this.location; - } - - @Override - public BakedModel getValue() { - return modelRegistry.get(this.location); - } - - @Override - public BakedModel setValue(BakedModel value) { - return modelRegistry.put(this.location, value); - } - } - } -} diff --git a/src/main/java/org/embeddedt/modernfix/neoforge/dynresources/ModelLocationBuilder.java b/src/main/java/org/embeddedt/modernfix/neoforge/dynresources/ModelLocationBuilder.java deleted file mode 100644 index 6dbf84d3..00000000 --- a/src/main/java/org/embeddedt/modernfix/neoforge/dynresources/ModelLocationBuilder.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.embeddedt.modernfix.neoforge.dynresources; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.properties.Property; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -public class ModelLocationBuilder { - private final Map, PropertyData> propertyToOptionStrings = new Object2ObjectOpenHashMap<>(); - private final StringBuilder builder = new StringBuilder(); - - private record PropertyData(ImmutableList nameValuePairs, int maxPairLength) {} - - public void generateForBlock(Set destinationSet, Block block, ResourceLocation baseLocation) { - var props = block.getStateDefinition().getProperties(); - List> optionsList = new ArrayList<>(props.size()); - int requiredBuilderSize = Math.max(0, props.size() - 1); // commas - for (var prop : props) { - var data = propertyToOptionStrings.computeIfAbsent(prop, ModelLocationBuilder::computePropertyOptions); - optionsList.add(data.nameValuePairs); - requiredBuilderSize += data.maxPairLength; - } - var product = Lists.cartesianProduct(optionsList); - int count = product.size(); - int tupleEntryCount = optionsList.size(); - StringBuilder stringbuilder = this.builder; - stringbuilder.ensureCapacity(requiredBuilderSize); - for (int i = 0; i < count; i++) { - stringbuilder.setLength(0); - var result = product.get(i); - for (int j = 0; j < tupleEntryCount; j++) { - if (j != 0) { - stringbuilder.append(','); - } - stringbuilder.append(result.get(j)); - } - destinationSet.add(new ModelResourceLocation(baseLocation, stringbuilder.toString())); - } - } - - private static PropertyData computePropertyOptions(Property prop) { - ImmutableList.Builder valuesList = ImmutableList.builderWithExpectedSize(prop.getPossibleValues().size()); - int maxLength = 0; - for (var val : prop.getPossibleValues()) { - String pair = prop.getName() + "=" + getValueName(prop, val); - valuesList.add(pair.toLowerCase(Locale.ROOT)); - maxLength = Math.max(pair.length(), maxLength); - } - return new PropertyData(valuesList.build(), maxLength); - } - - private static > String getValueName(Property property, Comparable value) { - return property.getName((T)value); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/neoforge/init/ModernFixClientForge.java b/src/main/java/org/embeddedt/modernfix/neoforge/init/ModernFixClientForge.java index 9c2a5b4a..e7edc779 100644 --- a/src/main/java/org/embeddedt/modernfix/neoforge/init/ModernFixClientForge.java +++ b/src/main/java/org/embeddedt/modernfix/neoforge/init/ModernFixClientForge.java @@ -1,9 +1,14 @@ package org.embeddedt.modernfix.neoforge.init; -import com.mojang.blaze3d.platform.InputConstants; -import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.DebugScreenOverlay; +import net.minecraft.client.gui.components.debug.DebugScreenDisplayer; +import net.minecraft.client.gui.components.debug.DebugScreenEntry; +import net.minecraft.client.gui.components.debug.DebugScreenEntryStatus; +import net.minecraft.client.gui.components.debug.DebugScreenProfile; +import net.minecraft.resources.Identifier; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.chunk.LevelChunk; import net.neoforged.bus.api.EventPriority; import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.SubscribeEvent; @@ -11,39 +16,28 @@ import net.neoforged.fml.ModContainer; import net.neoforged.fml.ModLoader; import net.neoforged.fml.ModLoadingIssue; import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; -import net.neoforged.neoforge.client.event.ClientTickEvent; -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.RecipesReceivedEvent; +import net.neoforged.neoforge.client.event.RegisterDebugEntriesEvent; import net.neoforged.neoforge.client.event.RenderFrameEvent; import net.neoforged.neoforge.client.gui.IConfigScreenFactory; -import net.neoforged.neoforge.client.settings.KeyConflictContext; import net.neoforged.neoforge.event.TagsUpdatedEvent; import net.neoforged.neoforge.event.level.LevelEvent; import net.neoforged.neoforge.event.server.ServerStartedEvent; +import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.ModernFixClient; import org.embeddedt.modernfix.screen.ModernFixConfigScreen; - -import java.util.ArrayList; -import java.util.List; +import org.jspecify.annotations.Nullable; public class ModernFixClientForge { private static ModernFixClient commonMod; public ModernFixClientForge(ModContainer modContainer, IEventBus modBus) { commonMod = new ModernFixClient(); - modBus.addListener(this::keyBindRegister); modBus.addListener(this::onClientSetup); + modBus.addListener(this::onRenderOverlay); modContainer.registerExtensionPoint(IConfigScreenFactory.class, (mc, screen) -> new ModernFixConfigScreen(screen)); } - private KeyMapping configKey; - - private void keyBindRegister(RegisterKeyMappingsEvent event) { - configKey = new KeyMapping("key.modernfix.config", KeyConflictContext.UNIVERSAL, InputConstants.UNKNOWN, "key.modernfix"); - event.register(configKey); - } - private void onClientSetup(FMLClientSetupEvent event) { if(false) { event.enqueueWork(() -> { @@ -52,42 +46,25 @@ public class ModernFixClientForge { } } - @SubscribeEvent - public void onConfigKey(ClientTickEvent.Pre event) { - if(configKey != null && configKey.consumeClick()) { - Minecraft.getInstance().setScreen(new ModernFixConfigScreen(Minecraft.getInstance().screen)); - } - } + private static final Identifier MODERNFIX_VERSION = Identifier.fromNamespaceAndPath(ModernFix.MODID, "version"); - private static final List brandingList = new ArrayList<>(); - - @SubscribeEvent(priority = EventPriority.HIGHEST) - public void onRenderOverlay(CustomizeGuiOverlayEvent.DebugText event) { - if(commonMod.brandingString != null && Minecraft.getInstance().getDebugOverlay().showDebugScreen()) { - if(brandingList.size() == 0) { - brandingList.add(""); - brandingList.add(commonMod.brandingString); - } - int targetIdx = 0, numSeenBlanks = 0; - List right = event.getRight(); - while(targetIdx < right.size()) { - String s = right.get(targetIdx); - if(s == null || s.length() == 0) { - numSeenBlanks++; + private void onRenderOverlay(RegisterDebugEntriesEvent event) { + event.register(MODERNFIX_VERSION, new DebugScreenEntry() { + @Override + public void display(DebugScreenDisplayer displayer, @Nullable Level level, @Nullable LevelChunk clientChunk, @Nullable LevelChunk serverChunk) { + if (commonMod.brandingString != null) { + displayer.addToGroup(MODERNFIX_VERSION, commonMod.brandingString); } - if(numSeenBlanks == 3) - break; - targetIdx++; } - right.addAll(targetIdx, brandingList); - } + }); + event.includeInProfile(MODERNFIX_VERSION, DebugScreenProfile.DEFAULT, DebugScreenEntryStatus.IN_OVERLAY); } @SubscribeEvent public void onDisconnect(LevelEvent.Unload event) { if(event.getLevel().isClientSide()) { DebugScreenOverlay overlay = Minecraft.getInstance().getDebugOverlay(); - Minecraft.getInstance().tell(overlay::clearChunkCache); + Minecraft.getInstance().schedule(overlay::clearChunkCache); } } @@ -102,7 +79,7 @@ public class ModernFixClientForge { } @SubscribeEvent(priority = EventPriority.LOWEST) - public void onRecipes(RecipesUpdatedEvent e) { + public void onRecipes(RecipesReceivedEvent e) { commonMod.onRecipesUpdated(); } diff --git a/src/main/java/org/embeddedt/modernfix/neoforge/init/ModernFixForge.java b/src/main/java/org/embeddedt/modernfix/neoforge/init/ModernFixForge.java index c7bdbc53..72520a99 100644 --- a/src/main/java/org/embeddedt/modernfix/neoforge/init/ModernFixForge.java +++ b/src/main/java/org/embeddedt/modernfix/neoforge/init/ModernFixForge.java @@ -2,7 +2,7 @@ package org.embeddedt.modernfix.neoforge.init; import com.google.common.collect.ImmutableList; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.item.Item; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.EventPriority; @@ -10,7 +10,6 @@ import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.*; import net.neoforged.fml.common.Mod; -import net.neoforged.fml.config.ModConfig; import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; import net.neoforged.fml.loading.FMLEnvironment; import net.neoforged.fml.loading.FMLLoader; @@ -18,13 +17,10 @@ import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.event.server.ServerStartedEvent; import net.neoforged.neoforge.event.server.ServerStoppedEvent; import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; -import net.neoforged.neoforge.network.registration.PayloadRegistrar; import net.neoforged.neoforge.registries.RegisterEvent; import org.apache.commons.lang3.tuple.Pair; import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.core.ModernFixMixinPlugin; -import org.embeddedt.modernfix.neoforge.ModernFixConfig; -import org.embeddedt.modernfix.neoforge.packet.SmartIngredientSyncPayload; import java.util.List; @@ -40,10 +36,9 @@ public class ModernFixForge { modBus.addListener(this::commonSetup); modBus.addListener(this::registerItems); modBus.addListener(this::registerNetworkChannel); - if(FMLEnvironment.dist == Dist.CLIENT) { + if(FMLEnvironment.getDist() == Dist.CLIENT) { NeoForge.EVENT_BUS.register(new ModernFixClientForge(modContainer, modBus)); } - modContainer.registerConfig(ModConfig.Type.COMMON, ModernFixConfig.COMMON_CONFIG); } private void registerItems(RegisterEvent event) { @@ -51,7 +46,7 @@ public class ModernFixForge { event.register(Registries.ITEM, helper -> { Item.Properties props = new Item.Properties(); for(int i = 0; i < 1000000; i++) { - helper.register(ResourceLocation.fromNamespaceAndPath("modernfix", "item_" + i), new Item(props)); + helper.register(Identifier.fromNamespaceAndPath("modernfix", "item_" + i), new Item(props)); } }); } @@ -66,7 +61,7 @@ public class ModernFixForge { event.enqueueWork(() -> { boolean atLeastOneWarning = false; for(Pair, String> warning : MOD_WARNINGS) { - boolean isPresent = !FMLLoader.isProduction() || warning.getLeft().stream().anyMatch(name -> ModList.get().isLoaded(name)); + boolean isPresent = !FMLLoader.getCurrent().isProduction() || warning.getLeft().stream().anyMatch(name -> ModList.get().isLoaded(name)); if(!isPresent) { atLeastOneWarning = true; ModLoader.addLoadingIssue(ModLoadingIssue.warning(warning.getRight())); @@ -79,15 +74,7 @@ public class ModernFixForge { } private void registerNetworkChannel(final RegisterPayloadHandlersEvent event) { - if (ModernFixMixinPlugin.instance.isOptionEnabled("perf.smart_ingredient_sync.Channel")) { - // Sets the current network version - final PayloadRegistrar registrar = event.registrar("1").optional(); - registrar.playToClient( - SmartIngredientSyncPayload.TYPE, - SmartIngredientSyncPayload.STREAM_CODEC, - (payload, ctx) -> {} - ); - } + } @SubscribeEvent(priority = EventPriority.LOWEST) diff --git a/src/main/java/org/embeddedt/modernfix/neoforge/packet/SmartIngredientSyncPayload.java b/src/main/java/org/embeddedt/modernfix/neoforge/packet/SmartIngredientSyncPayload.java deleted file mode 100644 index 26d36914..00000000 --- a/src/main/java/org/embeddedt/modernfix/neoforge/packet/SmartIngredientSyncPayload.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.embeddedt.modernfix.neoforge.packet; - -import net.minecraft.network.RegistryFriendlyByteBuf; -import net.minecraft.network.codec.StreamCodec; -import net.minecraft.network.protocol.common.custom.CustomPacketPayload; -import net.minecraft.resources.ResourceLocation; -import org.embeddedt.modernfix.ModernFix; - -public enum SmartIngredientSyncPayload implements CustomPacketPayload { - INSTANCE; - - public static final ThreadLocal CLIENT_HAS_SMART_INGREDIENT_SYNC = ThreadLocal.withInitial(() -> false); - - public static final CustomPacketPayload.Type TYPE = new CustomPacketPayload.Type<>(ResourceLocation.fromNamespaceAndPath(ModernFix.MODID, "ingredient_sync")); - public static final StreamCodec STREAM_CODEC = StreamCodec.unit(INSTANCE); - - @Override - public Type type() { - return TYPE; - } -} \ No newline at end of file diff --git a/src/main/java/org/embeddedt/modernfix/neoforge/recipe/IngredientValueDeduplicator.java b/src/main/java/org/embeddedt/modernfix/neoforge/recipe/IngredientValueDeduplicator.java deleted file mode 100644 index 0a902508..00000000 --- a/src/main/java/org/embeddedt/modernfix/neoforge/recipe/IngredientValueDeduplicator.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.embeddedt.modernfix.neoforge.recipe; - -import com.google.common.math.IntMath; -import it.unimi.dsi.fastutil.Hash; -import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet; -import it.unimi.dsi.fastutil.objects.Reference2ObjectMaps; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Ingredient; -import org.embeddedt.modernfix.common.mixin.perf.ingredient_item_deduplication.PatchedDataComponentMapAccessor; - -/** - * @author embeddedt (original inspiration from Uncandango's AllTheLeaks mod) - */ -public class IngredientValueDeduplicator { - private static final ObjectOpenCustomHashSet VALUES = new ObjectOpenCustomHashSet<>(new Hash.Strategy<>() { - @Override - public int hashCode(Ingredient.ItemValue o) { - if (o == null) { - return 0; - } - var stack = o.item(); - int hash = 31 * stack.getItem().hashCode(); - if (stack.getComponents() instanceof PatchedDataComponentMapAccessor comps) { - var patch = comps.mfix$getPatch(); - for (var entry : Reference2ObjectMaps.fastIterable(patch)) { - int keyHash = System.identityHashCode(entry.getKey()) & 0xff; - var value = entry.getValue(); - int valueHash = value.isPresent() ? System.identityHashCode(value.get()) : 0; - hash += IntMath.pow(31, keyHash) * valueHash; - } - } else { - hash += System.identityHashCode(stack.getComponents()); - } - return hash; - } - - private boolean areComponentsSame(ItemStack a, ItemStack b) { - // Compare using stricter logic than vanilla: require the prototype maps to be equal, and require - // the values in the patch to also be identity-equal. This works around Neo allowing Holder.Reference objects - // made with the server & client registries to be considered equal. - if (a.getComponents() instanceof PatchedDataComponentMapAccessor aComps && b.getComponents() instanceof PatchedDataComponentMapAccessor bComps) { - if (!aComps.mfix$getPrototype().equals(bComps.mfix$getPrototype())) { - return false; - } - var aPatch = aComps.mfix$getPatch(); - var bPatch = bComps.mfix$getPatch(); - if (aPatch != bPatch) { - if (aPatch.size() != bPatch.size()) { - return false; - } - for (var entry : Reference2ObjectMaps.fastIterable(aPatch)) { - var value = bPatch.get(entry.getKey()); - if (value == null) { - return false; - } - if (value.isPresent() != entry.getValue().isPresent()) { - return false; - } else if (value.isPresent() && value.get() != entry.getValue().get()) { - return false; - } - } - } - return true; - } else { - return a.getComponents() == b.getComponents(); - } - } - - private boolean areStacksSame(ItemStack a, ItemStack b) { - if (!a.is(b.getItem())) { - return false; - } - if (a.isEmpty() != b.isEmpty()) { - return false; - } - if (!areComponentsSame(a, b)) { - return false; - } - return a.getCount() == b.getCount(); - } - - @Override - public boolean equals(Ingredient.ItemValue a, Ingredient.ItemValue b) { - return a == b || a != null && b != null && areStacksSame(a.item(), b.item()); - } - }); - - public static Ingredient.Value deduplicate(Ingredient.Value value) { - if (value != null && value.getClass() == Ingredient.ItemValue.class) { - synchronized (VALUES) { - return VALUES.addOrGet((Ingredient.ItemValue)value); - } - } else { - return value; - } - } -} diff --git a/src/main/java/org/embeddedt/modernfix/platform/neoforge/ModernFixPlatformHooksImpl.java b/src/main/java/org/embeddedt/modernfix/platform/neoforge/ModernFixPlatformHooksImpl.java index ee8aee0d..5024ac43 100644 --- a/src/main/java/org/embeddedt/modernfix/platform/neoforge/ModernFixPlatformHooksImpl.java +++ b/src/main/java/org/embeddedt/modernfix/platform/neoforge/ModernFixPlatformHooksImpl.java @@ -35,11 +35,11 @@ import java.util.function.Consumer; public class ModernFixPlatformHooksImpl implements ModernFixPlatformHooks { public boolean isClient() { - return FMLLoader.getDist() == Dist.CLIENT; + return FMLLoader.getCurrent().getDist() == Dist.CLIENT; } public boolean isDedicatedServer() { - return FMLLoader.getDist().isDedicatedServer(); + return FMLLoader.getCurrent().getDist().isDedicatedServer(); } private static final String verString = Optional.ofNullable( @@ -51,11 +51,11 @@ public class ModernFixPlatformHooksImpl implements ModernFixPlatformHooks { } public boolean modPresent(String modId) { - return FMLLoader.getLoadingModList().getModFileById(modId) != null; + return FMLLoader.getCurrent().getLoadingModList().getModFileById(modId) != null; } public boolean isDevEnv() { - return !FMLLoader.isProduction(); + return !FMLLoader.getCurrent().isProduction(); } public MinecraftServer getCurrentServer() { diff --git a/src/main/java/org/embeddedt/modernfix/render/SimpleItemModelView.java b/src/main/java/org/embeddedt/modernfix/render/SimpleItemModelView.java deleted file mode 100644 index ff2c2312..00000000 --- a/src/main/java/org/embeddedt/modernfix/render/SimpleItemModelView.java +++ /dev/null @@ -1,94 +0,0 @@ -package org.embeddedt.modernfix.render; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import net.minecraft.client.renderer.block.model.BakedQuad; -import net.minecraft.client.renderer.block.model.ItemOverrides; -import net.minecraft.client.renderer.block.model.ItemTransforms; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.core.Direction; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.block.state.BlockState; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -/** - * Wrapper class that presents a fake view of item models (only showing the simple front-facing quads), rather - * than every quad. - */ -public class SimpleItemModelView implements BakedModel { - private BakedModel wrappedItem; - private FastItemRenderType type; - - public void setItem(BakedModel model) { - this.wrappedItem = model; - } - - public void setType(FastItemRenderType type) { - this.type = type; - } - - private boolean isCorrectDirectionForType(Direction direction) { - if(type == FastItemRenderType.SIMPLE_ITEM) - return direction == Direction.SOUTH; - else { - return direction == Direction.UP || direction == Direction.EAST || direction == Direction.NORTH; - } - } - - private final List nullQuadList = new ObjectArrayList<>(); - - @Override - public List getQuads(@Nullable BlockState state, @Nullable Direction side, RandomSource rand) { - boolean isWholeListValid = isCorrectDirectionForType(side); - List realList = wrappedItem.getQuads(state, side, rand); - if (isWholeListValid) { - return realList; - } - nullQuadList.clear(); - //noinspection ForLoopReplaceableByForEach - for(int i = 0; i < realList.size(); i++) { - BakedQuad quad = realList.get(i); - if(isCorrectDirectionForType(quad.getDirection())) { - nullQuadList.add(quad); - } - } - return nullQuadList; - } - - @Override - public boolean useAmbientOcclusion() { - return wrappedItem.useAmbientOcclusion(); - } - - @Override - public boolean isGui3d() { - return wrappedItem.isGui3d(); - } - - @Override - public boolean usesBlockLight() { - return wrappedItem.usesBlockLight(); - } - - @Override - public boolean isCustomRenderer() { - return wrappedItem.isCustomRenderer(); - } - - @Override - public TextureAtlasSprite getParticleIcon() { - return wrappedItem.getParticleIcon(); - } - - @Override - public ItemTransforms getTransforms() { - return wrappedItem.getTransforms(); - } - - @Override - public ItemOverrides getOverrides() { - return wrappedItem.getOverrides(); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/resources/PackResourcesCacheEngine.java b/src/main/java/org/embeddedt/modernfix/resources/PackResourcesCacheEngine.java index 64319278..bb54e8f5 100644 --- a/src/main/java/org/embeddedt/modernfix/resources/PackResourcesCacheEngine.java +++ b/src/main/java/org/embeddedt/modernfix/resources/PackResourcesCacheEngine.java @@ -5,7 +5,7 @@ import com.google.common.base.Stopwatch; import com.google.common.collect.ImmutableList; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.packs.PackResources; import net.minecraft.server.packs.PackType; import org.embeddedt.modernfix.ModernFix; @@ -75,7 +75,7 @@ public class PackResourcesCacheEngine { void outputResources(String namespace, Path baseNioPath, String path, PackResources.ResourceOutput output) { if (children.isEmpty()) { // This is a terminal node. - ResourceLocation location = ResourceLocation.fromNamespaceAndPath(namespace, path); + Identifier location = Identifier.fromNamespaceAndPath(namespace, path); output.accept(location, () -> Files.newInputStream(baseNioPath.resolve(path))); } else { for (var entry : children.entrySet()) { @@ -144,7 +144,7 @@ public class PackResourcesCacheEngine { if(str.length() == 0) return false; for(int i = 0; i < str.length(); i++) { - if(!ResourceLocation.validPathChar(str.charAt(i))) { + if(!Identifier.validPathChar(str.charAt(i))) { return false; } } diff --git a/src/main/java/org/embeddedt/modernfix/screen/ModernFixConfigScreen.java b/src/main/java/org/embeddedt/modernfix/screen/ModernFixConfigScreen.java index 8ebe740f..7db99524 100644 --- a/src/main/java/org/embeddedt/modernfix/screen/ModernFixConfigScreen.java +++ b/src/main/java/org/embeddedt/modernfix/screen/ModernFixConfigScreen.java @@ -5,7 +5,7 @@ import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; -import net.minecraft.Util; +import net.minecraft.util.Util; public class ModernFixConfigScreen extends Screen { private OptionList optionList; diff --git a/src/main/java/org/embeddedt/modernfix/screen/OptionList.java b/src/main/java/org/embeddedt/modernfix/screen/OptionList.java index 06fe5207..a40d974d 100644 --- a/src/main/java/org/embeddedt/modernfix/screen/OptionList.java +++ b/src/main/java/org/embeddedt/modernfix/screen/OptionList.java @@ -11,6 +11,7 @@ import net.minecraft.client.gui.components.ContainerObjectSelectionList; import net.minecraft.client.gui.components.Tooltip; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.narration.NarratableEntry; +import net.minecraft.client.input.MouseButtonEvent; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.HoverEvent; @@ -41,7 +42,7 @@ public class OptionList extends ContainerObjectSelectionList { String friendlyKey = "modernfix.option.name." + option.getName(); MutableComponent baseComponent = Component.literal(option.getSelfName()); if(I18n.exists(friendlyKey)) - return Component.translatable(friendlyKey).withStyle(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, baseComponent))); + return Component.translatable(friendlyKey).withStyle(style -> style.withHoverEvent(new HoverEvent.ShowText(baseComponent))); else return baseComponent; } @@ -78,7 +79,7 @@ public class OptionList extends ContainerObjectSelectionList { for(String category : theCategories) { String categoryTranslationKey = "modernfix.option.category." + category; this.addEntry(new CategoryEntry(Component.translatable(categoryTranslationKey) - .withStyle(Style.EMPTY.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable(categoryTranslationKey + ".description")))) + .withStyle(Style.EMPTY.withHoverEvent(new HoverEvent.ShowText(Component.translatable(categoryTranslationKey + ".description")))) )); optionsByCategory.get(category).stream().filter(key -> { int dotCount = 0; @@ -91,10 +92,6 @@ public class OptionList extends ContainerObjectSelectionList { } } - protected int getScrollbarPosition() { - return super.getScrollbarPosition() + 15 + 20; - } - public int getRowWidth() { return super.getRowWidth() + 32; } @@ -108,10 +105,10 @@ public class OptionList extends ContainerObjectSelectionList { this.width = OptionList.this.minecraft.font.width(this.name); } - public void render(GuiGraphics guiGraphics, int index, int top, int left, int width, int height, int mouseX, int mouseY, boolean isMouseOver, float partialTicks) { + public void renderContent(GuiGraphics guiGraphics, int mouseX, int mouseY, boolean isMouseOver, float partialTicks) { Font var10000 = OptionList.this.minecraft.font; float x = (float)(OptionList.this.minecraft.screen.width / 2 - this.width / 2); - int y = top + height - 10; + int y = 0 + height - 10; guiGraphics.drawString(var10000, this.name, (int)x, y, 16777215); /* if(mouseX >= x && mouseY >= y && mouseX <= (x + this.width) && mouseY <= (y + OptionList.this.minecraft.font.lineHeight)) @@ -166,7 +163,7 @@ public class OptionList extends ContainerObjectSelectionList { }).tooltip(toggleTooltip).pos(0, 0).size(55, 20).build(); updateStatus(); this.helpButton = new Button.Builder(Component.literal("?"), (arg) -> { - mainScreen.setLastScrollAmount(getScrollAmount()); + mainScreen.setLastScrollAmount(scrollAmount()); Minecraft.getInstance().setScreen(new ModernFixOptionInfoScreen(mainScreen, optionName)); }).pos(75, 0).size(20, 20).build(); if(!I18n.exists("modernfix.option." + optionName)) { @@ -181,7 +178,8 @@ public class OptionList extends ContainerObjectSelectionList { } @Override - public void render(GuiGraphics guiGraphics, int index, int top, int left, int width, int height, int mouseX, int mouseY, boolean isMouseOver, float partialTicks) { + public void renderContent(GuiGraphics guiGraphics, int mouseX, int mouseY, boolean isHovering, float partialTicks) { + int left = 0, top = 0; MutableComponent nameComponent = getOptionComponent(option); if(this.option.isUserDefined()) nameComponent = nameComponent.withStyle(style -> style.withItalic(true)).append(Component.translatable("modernfix.config.not_default")); @@ -209,17 +207,17 @@ public class OptionList extends ContainerObjectSelectionList { return ImmutableList.of(this.toggleButton, this.helpButton); } - public boolean mouseClicked(double mouseX, double mouseY, int button) { + public boolean mouseClicked(MouseButtonEvent event, boolean isDoubleClick) { for(GuiEventListener listener : children()) { - if(listener.mouseClicked(mouseX, mouseY, button)) + if(listener.mouseClicked(event, isDoubleClick)) return true; } return false; } - public boolean mouseReleased(double mouseX, double mouseY, int button) { + public boolean mouseReleased(MouseButtonEvent event) { for(GuiEventListener listener : children()) { - if(listener.mouseReleased(mouseX, mouseY, button)) + if(listener.mouseReleased(event)) return true; } return false; diff --git a/src/main/java/org/embeddedt/modernfix/spark/SparkLaunchProfiler.java b/src/main/java/org/embeddedt/modernfix/spark/SparkLaunchProfiler.java index 968a6afe..c251c99e 100644 --- a/src/main/java/org/embeddedt/modernfix/spark/SparkLaunchProfiler.java +++ b/src/main/java/org/embeddedt/modernfix/spark/SparkLaunchProfiler.java @@ -108,7 +108,7 @@ public class SparkLaunchProfiler { @Override public String getMinecraftVersion() { - return SharedConstants.getCurrentVersion().getName(); + return SharedConstants.getCurrentVersion().name(); } } diff --git a/src/main/java/org/embeddedt/modernfix/util/ItemMesherMap.java b/src/main/java/org/embeddedt/modernfix/util/ItemMesherMap.java deleted file mode 100644 index e2f61b6a..00000000 --- a/src/main/java/org/embeddedt/modernfix/util/ItemMesherMap.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.embeddedt.modernfix.util; - -import net.minecraft.client.resources.model.ModelResourceLocation; -import net.minecraft.core.registries.BuiltInRegistries; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; -import java.util.function.Function; - -public class ItemMesherMap implements Map { - private final Function getLocation; - - public ItemMesherMap(Function getLocation) { - this.getLocation = getLocation; - } - - @Override - public int size() { - return BuiltInRegistries.ITEM.keySet().size(); - } - - @Override - public boolean isEmpty() { - return false; - } - - @Override - public boolean containsKey(Object key) { - return true; - } - - @Override - public boolean containsValue(Object value) { - return false; - } - - @Override - public ModelResourceLocation get(Object key) { - return getLocation.apply((K)key); - } - - @Nullable - @Override - public ModelResourceLocation put(K key, ModelResourceLocation value) { - throw new UnsupportedOperationException(); - } - - @Override - public ModelResourceLocation remove(Object key) { - throw new UnsupportedOperationException(); - } - - @Override - public void putAll(@NotNull Map m) { - throw new UnsupportedOperationException(); - } - - @Override - public void clear() { - throw new UnsupportedOperationException(); - } - - @NotNull - @Override - public Set keySet() { - throw new UnsupportedOperationException(); - } - - @NotNull - @Override - public Collection values() { - throw new UnsupportedOperationException(); - } - - @NotNull - @Override - public Set> entrySet() { - throw new UnsupportedOperationException(); - } -} diff --git a/src/main/java/org/embeddedt/modernfix/util/NamedPreparableResourceListener.java b/src/main/java/org/embeddedt/modernfix/util/NamedPreparableResourceListener.java index a8729114..3a7dd85e 100644 --- a/src/main/java/org/embeddedt/modernfix/util/NamedPreparableResourceListener.java +++ b/src/main/java/org/embeddedt/modernfix/util/NamedPreparableResourceListener.java @@ -13,9 +13,15 @@ public class NamedPreparableResourceListener implements PreparableReloadListener this.delegate = delegate; } + @Override - public CompletableFuture reload(PreparationBarrier stage, ResourceManager resourceManager, ProfilerFiller preparationsProfiler, ProfilerFiller reloadProfiler, Executor backgroundExecutor, Executor gameExecutor) { - return this.delegate.reload(stage, resourceManager, preparationsProfiler, reloadProfiler, backgroundExecutor, gameExecutor); + public CompletableFuture reload(SharedState sharedState, Executor exectutor, PreparationBarrier barrier, Executor applyExectutor) { + return this.delegate.reload(sharedState, exectutor, barrier, applyExectutor); + } + + @Override + public void prepareSharedState(SharedState sharedState) { + this.delegate.prepareSharedState(sharedState); } @Override diff --git a/src/main/java/org/embeddedt/modernfix/world/IntegratedWatchdog.java b/src/main/java/org/embeddedt/modernfix/world/IntegratedWatchdog.java index b5e5e827..8e3017a4 100644 --- a/src/main/java/org/embeddedt/modernfix/world/IntegratedWatchdog.java +++ b/src/main/java/org/embeddedt/modernfix/world/IntegratedWatchdog.java @@ -2,7 +2,7 @@ package org.embeddedt.modernfix.world; import com.mojang.logging.LogUtils; import net.minecraft.DefaultUncaughtExceptionHandlerWithName; -import net.minecraft.Util; +import net.minecraft.util.Util; import net.minecraft.server.MinecraftServer; import org.embeddedt.modernfix.duck.ITimeTrackingServer; import org.slf4j.Logger; diff --git a/src/main/java/org/embeddedt/modernfix/world/StrongholdLocationCache.java b/src/main/java/org/embeddedt/modernfix/world/StrongholdLocationCache.java deleted file mode 100644 index 37c8d223..00000000 --- a/src/main/java/org/embeddedt/modernfix/world/StrongholdLocationCache.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.embeddedt.modernfix.world; - -import net.minecraft.core.Holder; -import net.minecraft.core.HolderLookup; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.Tag; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.datafix.DataFixTypes; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.dimension.DimensionType; -import net.minecraft.world.level.saveddata.SavedData; - -import java.util.ArrayList; -import java.util.List; - -public class StrongholdLocationCache extends SavedData { - private List chunkPosList; - public StrongholdLocationCache() { - super(); - chunkPosList = new ArrayList<>(); - } - - public static SavedData.Factory factory(ServerLevel serverLevel) { - // FIXME datafixer will probably throw on update - return new SavedData.Factory<>(StrongholdLocationCache::new, StrongholdLocationCache::load, DataFixTypes.SAVED_DATA_FORCED_CHUNKS); - } - - public List getChunkPosList() { - return new ArrayList<>(chunkPosList); - } - - public void setChunkPosList(List positions) { - this.chunkPosList = new ArrayList<>(positions); - this.setDirty(); - } - - public static StrongholdLocationCache load(CompoundTag arg, HolderLookup.Provider provider) { - StrongholdLocationCache cache = new StrongholdLocationCache(); - if(arg.contains("Positions", Tag.TAG_LONG_ARRAY)) { - long[] positions = arg.getLongArray("Positions"); - for(long position : positions) { - cache.chunkPosList.add(new ChunkPos(position)); - } - } - return cache; - } - - @Override - public CompoundTag save(CompoundTag compoundTag, HolderLookup.Provider provider) { - long[] serialized = new long[chunkPosList.size()]; - for(int i = 0; i < chunkPosList.size(); i++) { - ChunkPos thePos = chunkPosList.get(i); - serialized[i] = thePos.toLong(); - } - compoundTag.putLongArray("Positions", serialized); - return compoundTag; - } - - public static String getFileId(Holder dimensionType) { - return "mfix_strongholds"; - } -}