diff --git a/build.gradle b/build.gradle index 637a72d3..a943b5c9 100644 --- a/build.gradle +++ b/build.gradle @@ -37,14 +37,14 @@ dependencies { // Fabric API modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - modImplementation('com.terraformersmc:modmenu:4.0.4') { + modImplementation('com.terraformersmc:modmenu:5.0.2') { exclude group: 'net.fabricmc.fabric-api' } - modCompileOnly 'maven.modrinth:sodium:mc1.19-0.4.2' - modCompileOnly 'maven.modrinth:indium:1.0.7+mc1.19' - modCompileOnly 'io.vram:frex-fabric-mc119:6.0.278' - modCompileOnly 'io.vram:canvas-fabric-mc119:1.0.2453' + modCompileOnly 'maven.modrinth:sodium:mc1.19.3-0.4.9' + modCompileOnly 'maven.modrinth:indium:1.0.12+mc1.19.3' + modCompileOnly 'io.vram:frex-fabric-mc119:6.1.305' + modCompileOnly 'io.vram:canvas-fabric-mc119:1.0.2503' } String getExtraBuildMetadata() { diff --git a/gradle.properties b/gradle.properties index 91bf9458..dc032234 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,15 +3,15 @@ org.gradle.jvmargs = -Xmx1G # Fabric Properties loom_version = 1.1-SNAPSHOT - minecraft_version = 1.19 - yarn_mappings = 1.19+build.4 + minecraft_version = 1.19.3 + yarn_mappings = 1.19.3+build.5 loader_version = 0.14.13 # Mod Properties - mod_version = 2.0.2 - mod_minecraft_version = 1.19 + mod_version = 3.0.0-beta.2 + mod_minecraft_version = 1.19.3 maven_group = me.pepperbell archives_base_name = continuity # Dependencies - fabric_version = 0.58.0+1.19 + fabric_version = 0.71.0+1.19.3 diff --git a/src/main/java/me/pepperbell/continuity/api/client/CTMLoader.java b/src/main/java/me/pepperbell/continuity/api/client/CTMLoader.java index afb18734..b0f18e1c 100644 --- a/src/main/java/me/pepperbell/continuity/api/client/CTMLoader.java +++ b/src/main/java/me/pepperbell/continuity/api/client/CTMLoader.java @@ -5,17 +5,5 @@ public interface CTMLoader { QuadProcessorFactory getProcessorFactory(); - static CTMLoader of(CTMPropertiesFactory propertiesFactory, QuadProcessorFactory processorFactory) { - return new CTMLoader() { - @Override - public CTMPropertiesFactory getPropertiesFactory() { - return propertiesFactory; - } - - @Override - public QuadProcessorFactory getProcessorFactory() { - return processorFactory; - } - }; - } + CachingPredicatesFactory getPredicatesFactory(); } diff --git a/src/main/java/me/pepperbell/continuity/api/client/CTMProperties.java b/src/main/java/me/pepperbell/continuity/api/client/CTMProperties.java index 5649b460..6c979f90 100644 --- a/src/main/java/me/pepperbell/continuity/api/client/CTMProperties.java +++ b/src/main/java/me/pepperbell/continuity/api/client/CTMProperties.java @@ -2,22 +2,8 @@ import java.util.Collection; -import net.minecraft.block.BlockState; import net.minecraft.client.util.SpriteIdentifier; -import net.minecraft.util.Identifier; public interface CTMProperties extends Comparable { - boolean affectsTextures(); - - boolean affectsTexture(Identifier id); - - boolean affectsBlockStates(); - - boolean affectsBlockState(BlockState state); - Collection getTextureDependencies(); - - default boolean isValidForMultipass() { - return true; - } } diff --git a/src/main/java/me/pepperbell/continuity/api/client/CTMPropertiesFactory.java b/src/main/java/me/pepperbell/continuity/api/client/CTMPropertiesFactory.java index 839d4455..86be53f3 100644 --- a/src/main/java/me/pepperbell/continuity/api/client/CTMPropertiesFactory.java +++ b/src/main/java/me/pepperbell/continuity/api/client/CTMPropertiesFactory.java @@ -4,9 +4,11 @@ import org.jetbrains.annotations.Nullable; +import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.ResourcePack; import net.minecraft.util.Identifier; public interface CTMPropertiesFactory { @Nullable - T createProperties(Properties properties, Identifier id, String packName, int packPriority, String method); + T createProperties(Properties properties, Identifier id, ResourcePack pack, int packPriority, ResourceManager resourceManager, String method); } diff --git a/src/main/java/me/pepperbell/continuity/api/client/CachingPredicates.java b/src/main/java/me/pepperbell/continuity/api/client/CachingPredicates.java new file mode 100644 index 00000000..7a7e6acf --- /dev/null +++ b/src/main/java/me/pepperbell/continuity/api/client/CachingPredicates.java @@ -0,0 +1,16 @@ +package me.pepperbell.continuity.api.client; + +import net.minecraft.block.BlockState; +import net.minecraft.client.texture.Sprite; + +public interface CachingPredicates { + boolean affectsSprites(); + + boolean affectsSprite(Sprite sprite); + + boolean affectsBlockStates(); + + boolean affectsBlockState(BlockState state); + + boolean isValidForMultipass(); +} diff --git a/src/main/java/me/pepperbell/continuity/api/client/CachingPredicatesFactory.java b/src/main/java/me/pepperbell/continuity/api/client/CachingPredicatesFactory.java new file mode 100644 index 00000000..99cf28a9 --- /dev/null +++ b/src/main/java/me/pepperbell/continuity/api/client/CachingPredicatesFactory.java @@ -0,0 +1,10 @@ +package me.pepperbell.continuity.api.client; + +import java.util.function.Function; + +import net.minecraft.client.texture.Sprite; +import net.minecraft.client.util.SpriteIdentifier; + +public interface CachingPredicatesFactory { + CachingPredicates createPredicates(T properties, Function textureGetter); +} diff --git a/src/main/java/me/pepperbell/continuity/api/client/QuadProcessor.java b/src/main/java/me/pepperbell/continuity/api/client/QuadProcessor.java index bf22cc08..9e88a643 100644 --- a/src/main/java/me/pepperbell/continuity/api/client/QuadProcessor.java +++ b/src/main/java/me/pepperbell/continuity/api/client/QuadProcessor.java @@ -13,7 +13,7 @@ import net.minecraft.world.BlockRenderView; public interface QuadProcessor { - ProcessingResult processQuad(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, int processorIndex, ProcessingContext context); + ProcessingResult processQuad(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, ProcessingContext context); interface ProcessingContext extends ProcessingDataProvider { void addEmitterConsumer(Consumer consumer); diff --git a/src/main/java/me/pepperbell/continuity/client/ContinuityClient.java b/src/main/java/me/pepperbell/continuity/client/ContinuityClient.java index 66acc4d2..14c01dca 100644 --- a/src/main/java/me/pepperbell/continuity/client/ContinuityClient.java +++ b/src/main/java/me/pepperbell/continuity/client/ContinuityClient.java @@ -7,7 +7,9 @@ import me.pepperbell.continuity.api.client.CTMLoaderRegistry; import me.pepperbell.continuity.api.client.CTMProperties; import me.pepperbell.continuity.api.client.CTMPropertiesFactory; +import me.pepperbell.continuity.api.client.CachingPredicatesFactory; import me.pepperbell.continuity.api.client.QuadProcessorFactory; +import me.pepperbell.continuity.client.processor.BaseCachingPredicates; import me.pepperbell.continuity.client.processor.CompactCTMQuadProcessor; import me.pepperbell.continuity.client.processor.HorizontalQuadProcessor; import me.pepperbell.continuity.client.processor.HorizontalVerticalQuadProcessor; @@ -35,7 +37,6 @@ import me.pepperbell.continuity.client.properties.overlay.StandardConnectingOverlayCTMProperties; import me.pepperbell.continuity.client.properties.overlay.StandardOverlayCTMProperties; import me.pepperbell.continuity.client.resource.CustomBlockLayers; -import me.pepperbell.continuity.client.resource.EmissiveIdProvider; import me.pepperbell.continuity.client.util.RenderUtil; import me.pepperbell.continuity.client.util.biome.BiomeHolderManager; import me.pepperbell.continuity.client.util.biome.BiomeRetriever; @@ -44,6 +45,7 @@ import net.fabricmc.fabric.api.resource.ResourceManagerHelper; import net.fabricmc.fabric.api.resource.ResourcePackActivationType; import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.text.Text; import net.minecraft.util.Identifier; public class ContinuityClient implements ClientModInitializer { @@ -56,14 +58,13 @@ public void onInitializeClient() { ProcessingDataKeyRegistryImpl.INSTANCE.init(); BiomeHolderManager.init(); BiomeRetriever.init(); - EmissiveIdProvider.init(); ProcessingDataKeys.init(); RenderUtil.ReloadListener.init(); CustomBlockLayers.ReloadListener.init(); FabricLoader.getInstance().getModContainer(ID).ifPresent(container -> { - ResourceManagerHelper.registerBuiltinResourcePack(asId("default"), container, ResourcePackActivationType.NORMAL); - ResourceManagerHelper.registerBuiltinResourcePack(asId("glass_pane_culling_fix"), container, ResourcePackActivationType.NORMAL); + ResourceManagerHelper.registerBuiltinResourcePack(asId("default"), container, Text.translatable("resourcePack.continuity.default.name"), ResourcePackActivationType.NORMAL); + ResourceManagerHelper.registerBuiltinResourcePack(asId("glass_pane_culling_fix"), container, Text.translatable("resourcePack.continuity.glass_pane_culling_fix.name"), ResourcePackActivationType.NORMAL); }); // Regular methods @@ -95,7 +96,8 @@ public void onInitializeClient() { loader = createLoader( CompactConnectingCTMProperties::new, new TileAmountValidator.AtLeast<>(5), - new CompactCTMQuadProcessor.Factory() + new CompactCTMQuadProcessor.Factory(), + false ); registry.registerLoader("ctm_compact", loader); @@ -202,20 +204,47 @@ public void onInitializeClient() { registry.registerLoader("overlay_fixed", loader); } + private static CTMLoader createLoader(CTMPropertiesFactory propertiesFactory, QuadProcessorFactory processorFactory, CachingPredicatesFactory predicatesFactory) { + return new CTMLoader<>() { + @Override + public CTMPropertiesFactory getPropertiesFactory() { + return propertiesFactory; + } + + @Override + public QuadProcessorFactory getProcessorFactory() { + return processorFactory; + } + + @Override + public CachingPredicatesFactory getPredicatesFactory() { + return predicatesFactory; + } + }; + } + + private static CTMLoader createLoader(CTMPropertiesFactory propertiesFactory, TileAmountValidator validator, QuadProcessorFactory processorFactory, boolean isValidForMultipass) { + return createLoader(wrapWithOptifineOnlyCheck(TileAmountValidator.wrapFactory(BaseCTMProperties.wrapFactory(propertiesFactory), validator)), processorFactory, new BaseCachingPredicates.Factory<>(isValidForMultipass)); + } + private static CTMLoader createLoader(CTMPropertiesFactory propertiesFactory, TileAmountValidator validator, QuadProcessorFactory processorFactory) { - return CTMLoader.of(wrapWithOptifineOnlyCheck(TileAmountValidator.wrapFactory(BaseCTMProperties.wrapFactory(propertiesFactory), validator)), processorFactory); + return createLoader(propertiesFactory, validator, processorFactory, true); + } + + private static CTMLoader createLoader(CTMPropertiesFactory propertiesFactory, QuadProcessorFactory processorFactory, boolean isValidForMultipass) { + return createLoader(wrapWithOptifineOnlyCheck(BaseCTMProperties.wrapFactory(propertiesFactory)), processorFactory, new BaseCachingPredicates.Factory<>(isValidForMultipass)); } private static CTMLoader createLoader(CTMPropertiesFactory propertiesFactory, QuadProcessorFactory processorFactory) { - return CTMLoader.of(wrapWithOptifineOnlyCheck(BaseCTMProperties.wrapFactory(propertiesFactory)), processorFactory); + return createLoader(propertiesFactory, processorFactory, true); } private static CTMPropertiesFactory wrapWithOptifineOnlyCheck(CTMPropertiesFactory factory) { - return (properties, id, packName, packPriority, method) -> { + return (properties, id, pack, packPriority, resourceManager, method) -> { if (PropertiesParsingHelper.parseOptifineOnly(properties, id)) { return null; } - return factory.createProperties(properties, id, packName, packPriority, method); + return factory.createProperties(properties, id, pack, packPriority, resourceManager, method); }; } diff --git a/src/main/java/me/pepperbell/continuity/client/config/ContinuityConfigScreen.java b/src/main/java/me/pepperbell/continuity/client/config/ContinuityConfigScreen.java index 213691c8..fb7d0cc2 100644 --- a/src/main/java/me/pepperbell/continuity/client/config/ContinuityConfigScreen.java +++ b/src/main/java/me/pepperbell/continuity/client/config/ContinuityConfigScreen.java @@ -1,10 +1,10 @@ package me.pepperbell.continuity.client.config; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.screen.ScreenTexts; -import net.minecraft.text.StringVisitable; import net.minecraft.text.Text; public class ContinuityConfigScreen extends Screen { @@ -19,11 +19,19 @@ public ContinuityConfigScreen(Screen parent, ContinuityConfig config) { @Override protected void init() { - addDrawableChild(createBooleanOptionButton(width / 2 - 100 - 110, height / 2 - 10 - 12, 200, 20, config.connectedTextures)); - addDrawableChild(createBooleanOptionButton(width / 2 - 100 + 110, height / 2 - 10 - 12, 200, 20, config.emissiveTextures)); - addDrawableChild(createBooleanOptionButton(width / 2 - 100 - 110, height / 2 - 10 + 12, 200, 20, config.customBlockLayers)); + addDrawableChild(startBooleanOptionButton(config.connectedTextures) + .dimensions(width / 2 - 100 - 110, height / 2 - 10 - 12, 200, 20) + .build()); + addDrawableChild(startBooleanOptionButton(config.emissiveTextures) + .dimensions(width / 2 - 100 + 110, height / 2 - 10 - 12, 200, 20) + .build()); + addDrawableChild(startBooleanOptionButton(config.customBlockLayers) + .dimensions(width / 2 - 100 - 110, height / 2 - 10 + 12, 200, 20) + .build()); - addDrawableChild(new ButtonWidget(width / 2 - 100, height - 40, 200, 20, ScreenTexts.DONE, button -> close())); + addDrawableChild(ButtonWidget.builder(ScreenTexts.DONE, button -> close()) + .dimensions(width / 2 - 100, height - 40, 200, 20) + .build()); } @Override @@ -52,23 +60,16 @@ private static String getTooltipKey(String translationKey) { return translationKey + ".tooltip"; } - private ButtonWidget.TooltipSupplier createDefaultTooltipSupplier(StringVisitable text) { - return (button, matrices, mouseX, mouseY) -> { - renderOrderedTooltip(matrices, textRenderer.wrapLines(text, width / 100 * 100 / 2), mouseX, mouseY); - }; - } - - private ButtonWidget createBooleanOptionButton(int x, int y, int width, int height, Option option) { + private ButtonWidget.Builder startBooleanOptionButton(Option option) { String translationKey = getTranslationKey(option.getKey()); Text text = Text.translatable(translationKey); Text tooltipText = Text.translatable(getTooltipKey(translationKey)); - return new ButtonWidget(x, y, width, height, ScreenTexts.composeToggleText(text, option.get()), + return ButtonWidget.builder(ScreenTexts.composeToggleText(text, option.get()), button -> { boolean newValue = !option.get(); button.setMessage(ScreenTexts.composeToggleText(text, newValue)); option.set(newValue); - }, - createDefaultTooltipSupplier(tooltipText) - ); + }) + .tooltip(Tooltip.of(tooltipText)); } } diff --git a/src/main/java/me/pepperbell/continuity/client/mixin/AtlasLoaderMixin.java b/src/main/java/me/pepperbell/continuity/client/mixin/AtlasLoaderMixin.java new file mode 100644 index 00000000..6f04dfba --- /dev/null +++ b/src/main/java/me/pepperbell/continuity/client/mixin/AtlasLoaderMixin.java @@ -0,0 +1,87 @@ +package me.pepperbell.continuity.client.mixin; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.Supplier; + +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.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import me.pepperbell.continuity.client.resource.AtlasLoaderInitContext; +import me.pepperbell.continuity.client.resource.AtlasLoaderLoadContext; +import me.pepperbell.continuity.client.resource.EmissiveSuffixLoader; +import net.minecraft.client.texture.SpriteContents; +import net.minecraft.client.texture.SpriteLoader; +import net.minecraft.client.texture.atlas.AtlasLoader; +import net.minecraft.client.texture.atlas.AtlasSource; +import net.minecraft.client.texture.atlas.SingleAtlasSource; +import net.minecraft.resource.Resource; +import net.minecraft.resource.ResourceManager; +import net.minecraft.util.Identifier; + +@Mixin(AtlasLoader.class) +public class AtlasLoaderMixin { + @ModifyVariable(method = "(Ljava/util/List;)V", at = @At(value = "LOAD", ordinal = 0), argsOnly = true, ordinal = 0) + private List continuity$modifySources(List sources) { + AtlasLoaderInitContext context = AtlasLoaderInitContext.THREAD_LOCAL.get(); + if (context != null) { + Set extraIds = context.getExtraIdsFuture().join(); + if (extraIds != null && !extraIds.isEmpty()) { + List extraSources = new ObjectArrayList<>(); + for (Identifier extraId : extraIds) { + extraSources.add(new SingleAtlasSource(extraId, Optional.empty())); + } + + if (sources instanceof ArrayList) { + sources.addAll(0, extraSources); + } else { + List mutableSources = new ArrayList<>(extraSources); + mutableSources.addAll(sources); + return mutableSources; + } + } + } + return sources; + } + + @Inject(method = "loadSources(Lnet/minecraft/resource/ResourceManager;)Ljava/util/List;", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/ImmutableList;builder()Lcom/google/common/collect/ImmutableList$Builder;", remap = false), locals = LocalCapture.CAPTURE_FAILHARD) + private void continuity$afterLoadSources(ResourceManager resourceManager, CallbackInfoReturnable>> cir, Map suppliers) { + AtlasLoaderLoadContext context = AtlasLoaderLoadContext.THREAD_LOCAL.get(); + if (context != null) { + String emissiveSuffix = EmissiveSuffixLoader.getEmissiveSuffix(); + if (emissiveSuffix != null) { + Map extraSuppliers = new Object2ObjectOpenHashMap<>(); + Map emissiveIdMap = new Object2ObjectOpenHashMap<>(); + suppliers.forEach((id, supplier) -> { + if (!id.getPath().endsWith(emissiveSuffix)) { + Identifier emissiveId = new Identifier(id.getNamespace(), id.getPath() + emissiveSuffix); + if (!suppliers.containsKey(emissiveId)) { + Identifier emissiveLocation = emissiveId.withPath("textures/" + emissiveId.getPath() + ".png"); + Optional optionalResource = resourceManager.getResource(emissiveLocation); + if (optionalResource.isPresent()) { + Resource resource = optionalResource.get(); + extraSuppliers.put(emissiveId, () -> SpriteLoader.load(emissiveId, resource)); + emissiveIdMap.put(id, emissiveId); + } + } else { + emissiveIdMap.put(id, emissiveId); + } + } + }); + suppliers.putAll(extraSuppliers); + if (!emissiveIdMap.isEmpty()) { + context.setEmissiveIdMap(emissiveIdMap); + } + } + } + } +} diff --git a/src/main/java/me/pepperbell/continuity/client/mixin/BakedModelManagerMixin.java b/src/main/java/me/pepperbell/continuity/client/mixin/BakedModelManagerMixin.java new file mode 100644 index 00000000..2ee1d0f7 --- /dev/null +++ b/src/main/java/me/pepperbell/continuity/client/mixin/BakedModelManagerMixin.java @@ -0,0 +1,66 @@ +package me.pepperbell.continuity.client.mixin; + +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; + +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +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.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import me.pepperbell.continuity.client.resource.BakedModelManagerReloadExtension; +import net.minecraft.client.render.model.BakedModelManager; +import net.minecraft.client.render.model.ModelLoader; +import net.minecraft.client.render.model.SpriteAtlasManager; +import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.ResourceReloader; +import net.minecraft.util.Identifier; +import net.minecraft.util.profiler.Profiler; + +@Mixin(BakedModelManager.class) +public class BakedModelManagerMixin { + @Unique + @Nullable + private volatile BakedModelManagerReloadExtension continuity$reloadExtension; + + @Inject(method = "reload(Lnet/minecraft/resource/ResourceReloader$Synchronizer;Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/util/profiler/Profiler;Lnet/minecraft/util/profiler/Profiler;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;", at = @At("HEAD")) + private void continuity$onHeadReload(ResourceReloader.Synchronizer synchronizer, ResourceManager resourceManager, Profiler prepareProfiler, Profiler applyProfiler, Executor prepareExecutor, Executor applyExecutor, CallbackInfoReturnable> cir) { + continuity$reloadExtension = new BakedModelManagerReloadExtension(resourceManager, prepareExecutor); + + BakedModelManagerReloadExtension reloadExtension = this.continuity$reloadExtension; + if (reloadExtension != null) { + reloadExtension.setContext(); + } + } + + @Inject(method = "reload(Lnet/minecraft/resource/ResourceReloader$Synchronizer;Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/util/profiler/Profiler;Lnet/minecraft/util/profiler/Profiler;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;", at = @At("RETURN"), cancellable = true) + private void continuity$onReturnReload(ResourceReloader.Synchronizer synchronizer, ResourceManager resourceManager, Profiler prepareProfiler, Profiler applyProfiler, Executor prepareExecutor, Executor applyExecutor, CallbackInfoReturnable> cir) { + BakedModelManagerReloadExtension reloadExtension = this.continuity$reloadExtension; + if (reloadExtension != null) { + reloadExtension.clearContext(); + } + + cir.setReturnValue(cir.getReturnValue().thenRun(() -> this.continuity$reloadExtension = null)); + } + + @Inject(method = "bake(Lnet/minecraft/util/profiler/Profiler;Ljava/util/Map;Lnet/minecraft/client/render/model/ModelLoader;)Lnet/minecraft/client/render/model/BakedModelManager$BakingResult;", at = @At("HEAD")) + private void continuity$onHeadBake(Profiler profiler, Map preparations, ModelLoader modelLoader, CallbackInfoReturnable cir) { + BakedModelManagerReloadExtension reloadExtension = this.continuity$reloadExtension; + if (reloadExtension != null) { + reloadExtension.beforeBaking(preparations, modelLoader); + } + } + + @Inject(method = "upload(Lnet/minecraft/client/render/model/BakedModelManager$BakingResult;Lnet/minecraft/util/profiler/Profiler;)V", at = @At("RETURN")) + private void continuity$onReturnUpload(@Coerce Object bakingResult, Profiler profiler, CallbackInfo ci) { + BakedModelManagerReloadExtension reloadExtension = this.continuity$reloadExtension; + if (reloadExtension != null) { + reloadExtension.apply(); + } + } +} diff --git a/src/main/java/me/pepperbell/continuity/client/mixin/BlockModelsMixin.java b/src/main/java/me/pepperbell/continuity/client/mixin/BlockModelsMixin.java index a9b461f4..c3cae2d3 100644 --- a/src/main/java/me/pepperbell/continuity/client/mixin/BlockModelsMixin.java +++ b/src/main/java/me/pepperbell/continuity/client/mixin/BlockModelsMixin.java @@ -10,8 +10,8 @@ @Mixin(BlockModels.class) public class BlockModelsMixin { - @Inject(method = "reload()V", at = @At("HEAD")) - private void continuity$onHeadReload(CallbackInfo ci) { + @Inject(method = "setModels(Ljava/util/Map;)V", at = @At("HEAD")) + private void continuity$onHeadSetModels(CallbackInfo ci) { SpriteCalculator.clearCache(); } } diff --git a/src/main/java/me/pepperbell/continuity/client/mixin/ChunkRendererRegionMixin.java b/src/main/java/me/pepperbell/continuity/client/mixin/ChunkRendererRegionMixin.java index 6f175813..e8a816ff 100644 --- a/src/main/java/me/pepperbell/continuity/client/mixin/ChunkRendererRegionMixin.java +++ b/src/main/java/me/pepperbell/continuity/client/mixin/ChunkRendererRegionMixin.java @@ -6,8 +6,8 @@ import me.pepperbell.continuity.client.mixinterface.ChunkRendererRegionExtension; import net.minecraft.client.render.chunk.ChunkRendererRegion; +import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.registry.RegistryEntry; import net.minecraft.world.World; import net.minecraft.world.biome.Biome; diff --git a/src/main/java/me/pepperbell/continuity/client/mixin/ModelLoaderAccessor.java b/src/main/java/me/pepperbell/continuity/client/mixin/ModelLoaderAccessor.java deleted file mode 100644 index c3d24282..00000000 --- a/src/main/java/me/pepperbell/continuity/client/mixin/ModelLoaderAccessor.java +++ /dev/null @@ -1,16 +0,0 @@ -package me.pepperbell.continuity.client.mixin; - -import java.util.Map; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import net.minecraft.client.render.model.ModelLoader; -import net.minecraft.client.render.model.UnbakedModel; -import net.minecraft.util.Identifier; - -@Mixin(ModelLoader.class) -public interface ModelLoaderAccessor { - @Accessor("unbakedModels") - Map getUnbakedModels(); -} diff --git a/src/main/java/me/pepperbell/continuity/client/mixin/ModelLoaderBakerImplMixin.java b/src/main/java/me/pepperbell/continuity/client/mixin/ModelLoaderBakerImplMixin.java new file mode 100644 index 00000000..64cdf62b --- /dev/null +++ b/src/main/java/me/pepperbell/continuity/client/mixin/ModelLoaderBakerImplMixin.java @@ -0,0 +1,50 @@ +package me.pepperbell.continuity.client.mixin; + +import java.util.function.BiFunction; + +import org.spongepowered.asm.mixin.Mixin; +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.ModifyVariable; +import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import me.pepperbell.continuity.client.mixinterface.ModelLoaderExtension; +import me.pepperbell.continuity.client.resource.ModelWrappingHandler; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.ModelBakeSettings; +import net.minecraft.client.render.model.ModelLoader; +import net.minecraft.client.texture.Sprite; +import net.minecraft.client.util.SpriteIdentifier; +import net.minecraft.util.Identifier; + +@Mixin(targets = "net/minecraft/client/render/model/ModelLoader$BakerImpl") +public class ModelLoaderBakerImplMixin { + @Unique + private boolean continuity$wrapCTM; + + @Unique + private boolean continuity$wrapEmissive; + + @Inject(method = "(Lnet/minecraft/client/render/model/ModelLoader;Ljava/util/function/BiFunction;Lnet/minecraft/util/Identifier;)V", at = @At("TAIL")) + private void continuity$onTailInit(ModelLoader modelLoader, BiFunction spriteLoader, Identifier modelId, CallbackInfo ci) { + continuity$wrapCTM = ((ModelLoaderExtension) modelLoader).continuity$getWrapCTM(); + continuity$wrapEmissive = ((ModelLoaderExtension) modelLoader).continuity$getWrapEmissive(); + } + + @Inject(method = "bake(Lnet/minecraft/util/Identifier;Lnet/minecraft/client/render/model/ModelBakeSettings;)Lnet/minecraft/client/render/model/BakedModel;", slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/model/json/ItemModelGenerator;create(Ljava/util/function/Function;Lnet/minecraft/client/render/model/json/JsonUnbakedModel;)Lnet/minecraft/client/render/model/json/JsonUnbakedModel;")), at = @At(value = "RETURN", ordinal = 0), cancellable = true) + private void continuity$onReturnBakeGenerated(Identifier id, ModelBakeSettings settings, CallbackInfoReturnable cir) { + BakedModel model = cir.getReturnValue(); + BakedModel wrappedModel = ModelWrappingHandler.wrap(model, id, continuity$wrapCTM, continuity$wrapEmissive); + if (model != wrappedModel) { + cir.setReturnValue(wrappedModel); + } + } + + @ModifyVariable(method = "bake(Lnet/minecraft/util/Identifier;Lnet/minecraft/client/render/model/ModelBakeSettings;)Lnet/minecraft/client/render/model/BakedModel;", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/client/render/model/UnbakedModel;bake(Lnet/minecraft/client/render/model/Baker;Ljava/util/function/Function;Lnet/minecraft/client/render/model/ModelBakeSettings;Lnet/minecraft/util/Identifier;)Lnet/minecraft/client/render/model/BakedModel;")) + private BakedModel continuity$modifyBakedModel(BakedModel model, Identifier id, ModelBakeSettings settings) { + return ModelWrappingHandler.wrap(model, id, continuity$wrapCTM, continuity$wrapEmissive); + } +} diff --git a/src/main/java/me/pepperbell/continuity/client/mixin/ModelLoaderMixin.java b/src/main/java/me/pepperbell/continuity/client/mixin/ModelLoaderMixin.java index 762d192a..ec44e27b 100644 --- a/src/main/java/me/pepperbell/continuity/client/mixin/ModelLoaderMixin.java +++ b/src/main/java/me/pepperbell/continuity/client/mixin/ModelLoaderMixin.java @@ -1,85 +1,36 @@ package me.pepperbell.continuity.client.mixin; -import java.util.Map; - -import org.spongepowered.asm.mixin.Final; 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.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import com.mojang.datafixers.util.Pair; -import me.pepperbell.continuity.client.resource.CTMPropertiesLoader; -import me.pepperbell.continuity.client.resource.EmissiveSuffixLoader; -import me.pepperbell.continuity.client.resource.ModelWrappingHandler; -import me.pepperbell.continuity.client.resource.ResourcePackUtil; -import me.pepperbell.continuity.client.util.biome.BiomeHolderManager; -import net.minecraft.block.BlockState; -import net.minecraft.client.color.block.BlockColors; +import me.pepperbell.continuity.client.mixinterface.ModelLoaderExtension; import net.minecraft.client.render.model.ModelLoader; -import net.minecraft.client.render.model.UnbakedModel; -import net.minecraft.client.texture.SpriteAtlasTexture; -import net.minecraft.client.util.ModelIdentifier; -import net.minecraft.resource.ResourceManager; -import net.minecraft.util.Identifier; -import net.minecraft.util.profiler.Profiler; @Mixin(ModelLoader.class) -public class ModelLoaderMixin { - @Shadow - @Final - private Map unbakedModels; - @Shadow - @Final - private Map modelsToBake; - @Shadow - @Final - private Map> spriteAtlasData; - +public class ModelLoaderMixin implements ModelLoaderExtension { @Unique - private BlockState continuity$currentBlockState; - - @Inject(method = "(Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/client/color/block/BlockColors;Lnet/minecraft/util/profiler/Profiler;I)V", at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/util/profiler/Profiler;push(Ljava/lang/String;)V", args = "ldc=missing_model", shift = At.Shift.BEFORE)) - private void continuity$afterStoreArgs(ResourceManager resourceManager, BlockColors blockColors, Profiler profiler, int mipmap, CallbackInfo ci) { - // TODO: move these to the very beginning of resource reload - ResourcePackUtil.setup(resourceManager); - BiomeHolderManager.clearCache(); + private boolean continuity$wrapCTM; - EmissiveSuffixLoader.load(resourceManager); - CTMPropertiesLoader.clearAll(); - CTMPropertiesLoader.loadAll(resourceManager); - } + @Unique + private boolean continuity$wrapEmissive; - @Inject(method = "method_4716(Lnet/minecraft/block/BlockState;)V", at = @At("HEAD")) - private void continuity$onAddBlockStateModel(BlockState state, CallbackInfo ci) { - continuity$currentBlockState = state; + @Override + public boolean continuity$getWrapCTM() { + return continuity$wrapCTM; } - @Inject(method = "addModel(Lnet/minecraft/client/util/ModelIdentifier;)V", at = @At(value = "TAIL"), locals = LocalCapture.CAPTURE_FAILHARD) - private void continuity$afterAddModel(ModelIdentifier id, CallbackInfo ci, UnbakedModel model) { - if (continuity$currentBlockState != null) { - ModelWrappingHandler.onAddBlockStateModel(id, continuity$currentBlockState); - continuity$currentBlockState = null; - } + @Override + public void continuity$setWrapCTM(boolean wrapCTM) { + this.continuity$wrapCTM = wrapCTM; } - @Inject(method = "(Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/client/color/block/BlockColors;Lnet/minecraft/util/profiler/Profiler;I)V", at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/util/profiler/Profiler;swap(Ljava/lang/String;)V", args = "ldc=textures")) - private void continuity$onFinishAddingModels(ResourceManager resourceManager, BlockColors blockColors, Profiler profiler, int mipmap, CallbackInfo ci) { - ModelWrappingHandler.wrapCTMModels(unbakedModels, modelsToBake); + @Override + public boolean continuity$getWrapEmissive() { + return continuity$wrapEmissive; } - @Inject(method = "(Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/client/color/block/BlockColors;Lnet/minecraft/util/profiler/Profiler;I)V", at = @At("TAIL")) - private void continuity$onTailInit(ResourceManager resourceManager, BlockColors blockColors, Profiler profiler, int mipmap, CallbackInfo ci) { - ModelWrappingHandler.wrapEmissiveModels(spriteAtlasData, unbakedModels, modelsToBake); - - CTMPropertiesLoader.clearAll(); - - // TODO: move these to the very end of resource reload - ResourcePackUtil.clear(); - BiomeHolderManager.refreshHolders(); + @Override + public void continuity$setWrapEmissive(boolean wrapEmissive) { + this.continuity$wrapEmissive = wrapEmissive; } } diff --git a/src/main/java/me/pepperbell/continuity/client/mixin/SpriteAtlasTextureDataMixin.java b/src/main/java/me/pepperbell/continuity/client/mixin/SpriteAtlasTextureDataMixin.java deleted file mode 100644 index 2d72fc5a..00000000 --- a/src/main/java/me/pepperbell/continuity/client/mixin/SpriteAtlasTextureDataMixin.java +++ /dev/null @@ -1,28 +0,0 @@ -package me.pepperbell.continuity.client.mixin; - -import java.util.Map; - -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; - -import me.pepperbell.continuity.client.mixinterface.SpriteAtlasTextureDataExtension; -import net.minecraft.client.texture.SpriteAtlasTexture; -import net.minecraft.util.Identifier; - -@Mixin(SpriteAtlasTexture.Data.class) -public class SpriteAtlasTextureDataMixin implements SpriteAtlasTextureDataExtension { - @Unique - private Map continuity$emissiveIdMap; - - @Override - @Nullable - public Map continuity$getEmissiveIdMap() { - return continuity$emissiveIdMap; - } - - @Override - public void continuity$setEmissiveIdMap(Map map) { - continuity$emissiveIdMap = map; - } -} diff --git a/src/main/java/me/pepperbell/continuity/client/mixin/SpriteAtlasTextureMixin.java b/src/main/java/me/pepperbell/continuity/client/mixin/SpriteAtlasTextureMixin.java deleted file mode 100644 index 6806e533..00000000 --- a/src/main/java/me/pepperbell/continuity/client/mixin/SpriteAtlasTextureMixin.java +++ /dev/null @@ -1,103 +0,0 @@ -package me.pepperbell.continuity.client.mixin; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; -import java.util.stream.Stream; - -import org.spongepowered.asm.mixin.Final; -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.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import me.pepperbell.continuity.client.mixinterface.SpriteAtlasTextureDataExtension; -import me.pepperbell.continuity.client.mixinterface.SpriteExtension; -import me.pepperbell.continuity.client.resource.EmissiveIdProvider; -import me.pepperbell.continuity.client.resource.EmissiveSuffixLoader; -import net.minecraft.client.texture.Sprite; -import net.minecraft.client.texture.SpriteAtlasTexture; -import net.minecraft.resource.ResourceManager; -import net.minecraft.util.Identifier; -import net.minecraft.util.profiler.Profiler; - -@Mixin(SpriteAtlasTexture.class) -public class SpriteAtlasTextureMixin { - @Shadow - @Final - private Map sprites; - - @Unique - private boolean continuity$loadingEmissiveSprites; - @Unique - private Map continuity$emissiveIdMap; - - @Shadow - private Collection loadSprites(ResourceManager resourceManager, Set ids) { - return null; - } - - @Shadow - private Identifier getTexturePath(Identifier id) { - return null; - } - - @Inject(method = "loadSprites(Lnet/minecraft/resource/ResourceManager;Ljava/util/Set;)Ljava/util/Collection;", at = @At("TAIL")) - private void continuity$onTailLoadSprites(ResourceManager resourceManager, Set ids, CallbackInfoReturnable> cir) { - if (!continuity$loadingEmissiveSprites) { - continuity$loadingEmissiveSprites = true; - String emissiveSuffix = EmissiveSuffixLoader.getEmissiveSuffix(); - if (emissiveSuffix != null) { - Collection spriteInfos = cir.getReturnValue(); - Set emissiveIds = new ObjectOpenHashSet<>(); - continuity$emissiveIdMap = new Object2ObjectOpenHashMap<>(); - for (Sprite.Info spriteInfo : spriteInfos) { - Identifier id = spriteInfo.getId(); - Identifier emissiveId = EmissiveIdProvider.toEmissiveId(id, emissiveSuffix); - if (emissiveId != null) { - Identifier emissiveLocation = getTexturePath(emissiveId); - if (resourceManager.getResource(emissiveLocation).isPresent()) { - emissiveIds.add(emissiveId); - continuity$emissiveIdMap.put(id, emissiveId); - } - } - } - if (!emissiveIds.isEmpty()) { - Collection emissiveSpriteInfos = loadSprites(resourceManager, emissiveIds); - spriteInfos.addAll(emissiveSpriteInfos); - } else { - continuity$emissiveIdMap = null; - } - } - continuity$loadingEmissiveSprites = false; - } - } - - @Inject(method = "stitch(Lnet/minecraft/resource/ResourceManager;Ljava/util/stream/Stream;Lnet/minecraft/util/profiler/Profiler;I)Lnet/minecraft/client/texture/SpriteAtlasTexture$Data;", at = @At("TAIL")) - private void continuity$onTailStitch(ResourceManager resourceManager, Stream idStream, Profiler profiler, int mipmapLevel, CallbackInfoReturnable cir) { - SpriteAtlasTexture.Data data = cir.getReturnValue(); - ((SpriteAtlasTextureDataExtension) data).continuity$setEmissiveIdMap(continuity$emissiveIdMap); - continuity$emissiveIdMap = null; - } - - @Inject(method = "upload(Lnet/minecraft/client/texture/SpriteAtlasTexture$Data;)V", at = @At("TAIL")) - private void continuity$onTailUpload(SpriteAtlasTexture.Data data, CallbackInfo ci) { - Map emissiveIdMap = ((SpriteAtlasTextureDataExtension) data).continuity$getEmissiveIdMap(); - if (emissiveIdMap != null) { - emissiveIdMap.forEach((id, emissiveId) -> { - Sprite sprite = sprites.get(id); - if (sprite != null) { - Sprite emissiveSprite = sprites.get(emissiveId); - if (emissiveSprite != null) { - ((SpriteExtension) sprite).continuity$setEmissiveSprite(emissiveSprite); - } - } - }); - } - } -} diff --git a/src/main/java/me/pepperbell/continuity/client/mixin/SpriteLoaderMixin.java b/src/main/java/me/pepperbell/continuity/client/mixin/SpriteLoaderMixin.java new file mode 100644 index 00000000..f7e5e2e0 --- /dev/null +++ b/src/main/java/me/pepperbell/continuity/client/mixin/SpriteLoaderMixin.java @@ -0,0 +1,114 @@ +package me.pepperbell.continuity.client.mixin; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; +import java.util.function.Supplier; + +import org.jetbrains.annotations.Nullable; +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.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import me.pepperbell.continuity.client.mixinterface.SpriteExtension; +import me.pepperbell.continuity.client.resource.AtlasLoaderInitContext; +import me.pepperbell.continuity.client.resource.AtlasLoaderLoadContext; +import me.pepperbell.continuity.client.resource.SpriteLoaderLoadContext; +import me.pepperbell.continuity.client.resource.SpriteLoaderStitchContext; +import net.minecraft.client.texture.Sprite; +import net.minecraft.client.texture.SpriteContents; +import net.minecraft.client.texture.SpriteLoader; +import net.minecraft.util.Identifier; + +@Mixin(SpriteLoader.class) +public class SpriteLoaderMixin { + @Shadow + @Final + private Identifier id; + + @ModifyArg(method = "method_47661(Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/util/Identifier;ILjava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;", at = @At(value = "INVOKE", target = "Ljava/util/concurrent/CompletableFuture;supplyAsync(Ljava/util/function/Supplier;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;", ordinal = 0), index = 0) + private Supplier>> continuity$modifySupplier(Supplier>> supplier) { + SpriteLoaderLoadContext context = SpriteLoaderLoadContext.THREAD_LOCAL.get(); + if (context != null) { + CompletableFuture<@Nullable Set> extraIdsFuture = context.getExtraIdsFuture(id); + if (context.getEmissiveControl(id) != null) { + AtomicReference<@Nullable Map> emissiveIdMapHolder = context.getEmissiveIdMapHolder(); + return () -> { + AtlasLoaderInitContext.THREAD_LOCAL.set(() -> extraIdsFuture); + AtlasLoaderLoadContext.THREAD_LOCAL.set(emissiveIdMapHolder::set); + List> list = supplier.get(); + AtlasLoaderInitContext.THREAD_LOCAL.set(null); + AtlasLoaderLoadContext.THREAD_LOCAL.set(null); + return list; + }; + } + return () -> { + AtlasLoaderInitContext.THREAD_LOCAL.set(() -> extraIdsFuture); + List> list = supplier.get(); + AtlasLoaderInitContext.THREAD_LOCAL.set(null); + return list; + }; + } + return supplier; + } + + @ModifyArg(method = "method_47661(Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/util/Identifier;ILjava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;", at = @At(value = "INVOKE", target = "Ljava/util/concurrent/CompletableFuture;thenApply(Ljava/util/function/Function;)Ljava/util/concurrent/CompletableFuture;", ordinal = 0), index = 0) + private Function, SpriteLoader.StitchResult> continuity$modifyFunction(Function, SpriteLoader.StitchResult> function) { + SpriteLoaderLoadContext context = SpriteLoaderLoadContext.THREAD_LOCAL.get(); + if (context != null) { + SpriteLoaderLoadContext.EmissiveControl emissiveControl = context.getEmissiveControl(id); + if (emissiveControl != null) { + AtomicReference<@Nullable Map> emissiveIdMapHolder = context.getEmissiveIdMapHolder(); + return spriteContentsList -> { + Map emissiveIdMap = emissiveIdMapHolder.get(); + if (emissiveIdMap != null) { + SpriteLoaderStitchContext.THREAD_LOCAL.set(new SpriteLoaderStitchContext() { + @Override + public Map getEmissiveIdMap() { + return emissiveIdMap; + } + + @Override + public void markHasEmissives() { + emissiveControl.markHasEmissives(); + } + }); + SpriteLoader.StitchResult result = function.apply(spriteContentsList); + SpriteLoaderStitchContext.THREAD_LOCAL.set(null); + emissiveIdMapHolder.set(null); + return result; + } + return function.apply(spriteContentsList); + }; + } + } + return function; + } + + @Inject(method = "method_47663(Ljava/util/List;ILjava/util/concurrent/Executor;)Lnet/minecraft/client/texture/SpriteLoader$StitchResult;", at = @At("RETURN")) + private void continuity$onReturnStitch(List spriteContentsList, int mipmapLevels, Executor executor, CallbackInfoReturnable cir) { + SpriteLoaderStitchContext context = SpriteLoaderStitchContext.THREAD_LOCAL.get(); + if (context != null) { + Map emissiveIdMap = context.getEmissiveIdMap(); + Map sprites = cir.getReturnValue().regions(); + emissiveIdMap.forEach((id, emissiveId) -> { + Sprite sprite = sprites.get(id); + if (sprite != null) { + Sprite emissiveSprite = sprites.get(emissiveId); + if (emissiveSprite != null) { + ((SpriteExtension) sprite).continuity$setEmissiveSprite(emissiveSprite); + context.markHasEmissives(); + } + } + }); + } + } +} diff --git a/src/main/java/me/pepperbell/continuity/client/mixinterface/ChunkRendererRegionExtension.java b/src/main/java/me/pepperbell/continuity/client/mixinterface/ChunkRendererRegionExtension.java index b71d2280..14cac9d8 100644 --- a/src/main/java/me/pepperbell/continuity/client/mixinterface/ChunkRendererRegionExtension.java +++ b/src/main/java/me/pepperbell/continuity/client/mixinterface/ChunkRendererRegionExtension.java @@ -1,7 +1,7 @@ package me.pepperbell.continuity.client.mixinterface; +import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.registry.RegistryEntry; import net.minecraft.world.biome.Biome; public interface ChunkRendererRegionExtension { diff --git a/src/main/java/me/pepperbell/continuity/client/mixinterface/ModelLoaderExtension.java b/src/main/java/me/pepperbell/continuity/client/mixinterface/ModelLoaderExtension.java new file mode 100644 index 00000000..a40d0964 --- /dev/null +++ b/src/main/java/me/pepperbell/continuity/client/mixinterface/ModelLoaderExtension.java @@ -0,0 +1,11 @@ +package me.pepperbell.continuity.client.mixinterface; + +public interface ModelLoaderExtension { + boolean continuity$getWrapCTM(); + + void continuity$setWrapCTM(boolean wrapCTM); + + boolean continuity$getWrapEmissive(); + + void continuity$setWrapEmissive(boolean wrapEmissive); +} diff --git a/src/main/java/me/pepperbell/continuity/client/mixinterface/SpriteAtlasTextureDataExtension.java b/src/main/java/me/pepperbell/continuity/client/mixinterface/SpriteAtlasTextureDataExtension.java deleted file mode 100644 index e3cd4c4a..00000000 --- a/src/main/java/me/pepperbell/continuity/client/mixinterface/SpriteAtlasTextureDataExtension.java +++ /dev/null @@ -1,14 +0,0 @@ -package me.pepperbell.continuity.client.mixinterface; - -import java.util.Map; - -import org.jetbrains.annotations.Nullable; - -import net.minecraft.util.Identifier; - -public interface SpriteAtlasTextureDataExtension { - @Nullable - Map continuity$getEmissiveIdMap(); - - void continuity$setEmissiveIdMap(Map map); -} diff --git a/src/main/java/me/pepperbell/continuity/client/model/CTMBakedModel.java b/src/main/java/me/pepperbell/continuity/client/model/CTMBakedModel.java index 23073399..dea9ec48 100644 --- a/src/main/java/me/pepperbell/continuity/client/model/CTMBakedModel.java +++ b/src/main/java/me/pepperbell/continuity/client/model/CTMBakedModel.java @@ -1,10 +1,8 @@ package me.pepperbell.continuity.client.model; -import java.util.List; +import java.util.function.Function; import java.util.function.Supplier; -import org.jetbrains.annotations.Nullable; - import me.pepperbell.continuity.api.client.QuadProcessor; import me.pepperbell.continuity.client.config.ContinuityConfig; import me.pepperbell.continuity.client.util.RenderUtil; @@ -20,16 +18,14 @@ import net.minecraft.world.BlockRenderView; public class CTMBakedModel extends ForwardingBakedModel { - public static final int MULTIPASS_LIMIT = 3; + public static final int PASSES = 4; - protected final List processors; - @Nullable - protected final List multipassProcessors; + protected final BlockState defaultState; + protected volatile Function defaultSliceFunc; - public CTMBakedModel(BakedModel wrapped, List processors, @Nullable List multipassProcessors) { + public CTMBakedModel(BakedModel wrapped, BlockState defaultState) { this.wrapped = wrapped; - this.processors = processors; - this.multipassProcessors = multipassProcessors; + this.defaultState = defaultState; } @Override @@ -51,7 +47,7 @@ public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos return; } - quadTransform.prepare(processors, multipassProcessors, blockView, state, pos, randomSupplier, ContinuityConfig.INSTANCE.useManualCulling.get()); + quadTransform.prepare(blockView, state, pos, randomSupplier, ContinuityConfig.INSTANCE.useManualCulling.get(), getSliceFunc(state)); context.pushTransform(quadTransform); super.emitBlockQuads(blockView, state, pos, randomSupplier, context); @@ -66,17 +62,33 @@ public boolean isVanillaAdapter() { return false; } + protected Function getSliceFunc(BlockState state) { + if (state == defaultState) { + Function sliceFunc = defaultSliceFunc; + if (sliceFunc == null) { + synchronized (this) { + sliceFunc = defaultSliceFunc; + if (sliceFunc == null) { + defaultSliceFunc = QuadProcessors.getCache(state); + sliceFunc = defaultSliceFunc; + } + } + } + return sliceFunc; + } + return QuadProcessors.getCache(state); + } + protected static class CTMQuadTransform implements RenderContext.QuadTransform { protected final ProcessingContextImpl processingContext = new ProcessingContextImpl(); protected final CullingCache cullingCache = new CullingCache(); - protected List processors; - protected List multipassProcessors; protected BlockRenderView blockView; protected BlockState state; protected BlockPos pos; protected Supplier randomSupplier; protected boolean useManualCulling; + protected Function sliceFunc; protected boolean active; @@ -86,28 +98,22 @@ public boolean transform(MutableQuadView quad) { return false; } - Boolean result = transformOnce(quad, processors, 0); - if (result != null) { - return result; - } - if (multipassProcessors != null) { - for (int pass = 0; pass < MULTIPASS_LIMIT; pass++) { - result = transformOnce(quad, multipassProcessors, pass + 1); - if (result != null) { - return result; - } + for (int pass = 0; pass < PASSES; pass++) { + Boolean result = transformOnce(quad, pass); + if (result != null) { + return result; } } return true; } - protected Boolean transformOnce(MutableQuadView quad, List processors, int pass) { + protected Boolean transformOnce(MutableQuadView quad, int pass) { Sprite sprite = RenderUtil.getSpriteFinder().find(quad, 0); - int amount = processors.size(); - for (int i = 0; i < amount; i++) { - QuadProcessor processor = processors.get(i); - QuadProcessor.ProcessingResult result = processor.processQuad(quad, sprite, blockView, state, pos, randomSupplier, pass, i, processingContext); + QuadProcessors.Slice slice = sliceFunc.apply(sprite); + QuadProcessor[] processors = pass == 0 ? slice.processors() : slice.multipassProcessors(); + for (QuadProcessor processor : processors) { + QuadProcessor.ProcessingResult result = processor.processQuad(quad, sprite, blockView, state, pos, randomSupplier, pass, processingContext); if (result == QuadProcessor.ProcessingResult.CONTINUE) { continue; } @@ -128,14 +134,13 @@ public boolean isActive() { return active; } - public void prepare(List processors, List multipassProcessors, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, boolean useManualCulling) { - this.processors = processors; - this.multipassProcessors = multipassProcessors; + public void prepare(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, boolean useManualCulling, Function sliceFunc) { this.blockView = blockView; this.state = state; this.pos = pos; this.randomSupplier = randomSupplier; this.useManualCulling = useManualCulling; + this.sliceFunc = sliceFunc; active = true; @@ -144,13 +149,12 @@ public void prepare(List processors, List multipas } public void reset() { - processors = null; - multipassProcessors = null; blockView = null; state = null; pos = null; randomSupplier = null; useManualCulling = false; + sliceFunc = null; active = false; diff --git a/src/main/java/me/pepperbell/continuity/client/model/CTMUnbakedModel.java b/src/main/java/me/pepperbell/continuity/client/model/CTMUnbakedModel.java deleted file mode 100644 index a8403f65..00000000 --- a/src/main/java/me/pepperbell/continuity/client/model/CTMUnbakedModel.java +++ /dev/null @@ -1,64 +0,0 @@ -package me.pepperbell.continuity.client.model; - -import java.util.List; -import java.util.Set; -import java.util.function.Function; - -import org.jetbrains.annotations.Nullable; - -import com.google.common.collect.ImmutableList; -import com.mojang.datafixers.util.Pair; - -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import me.pepperbell.continuity.api.client.QuadProcessor; -import me.pepperbell.continuity.client.resource.CTMLoadingContainer; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.ModelBakeSettings; -import net.minecraft.client.render.model.ModelLoader; -import net.minecraft.client.render.model.UnbakedModel; -import net.minecraft.client.texture.Sprite; -import net.minecraft.client.util.SpriteIdentifier; -import net.minecraft.util.Identifier; - -public class CTMUnbakedModel extends WrappingUnbakedModel { - private final List> containerList; - @Nullable - private final List> multipassContainerList; - - public CTMUnbakedModel(UnbakedModel wrapped, List> containerList, @Nullable List> multipassContainerList) { - super(wrapped); - this.containerList = containerList; - this.multipassContainerList = multipassContainerList; - } - - @Override - public Set getTextureDependencies(Function unbakedModelGetter, Set> unresolvedTextureReferences) { - Set dependencies = new ObjectOpenHashSet<>(wrapped.getTextureDependencies(unbakedModelGetter, unresolvedTextureReferences)); - for (CTMLoadingContainer container : containerList) { - dependencies.addAll(container.getProperties().getTextureDependencies()); - } - if (multipassContainerList != null) { - for (CTMLoadingContainer container : multipassContainerList) { - dependencies.addAll(container.getProperties().getTextureDependencies()); - } - } - return dependencies; - } - - @Nullable - @Override - public BakedModel wrapBaked(@Nullable BakedModel bakedWrapped, ModelLoader loader, Function textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) { - if (bakedWrapped == null || bakedWrapped.isBuiltin()) { - return bakedWrapped; - } - return new CTMBakedModel(bakedWrapped, toProcessorList(containerList, textureGetter), multipassContainerList == null ? null : toProcessorList(multipassContainerList, textureGetter)); - } - - protected static ImmutableList toProcessorList(List> containerList, Function textureGetter) { - ImmutableList.Builder listBuilder = ImmutableList.builder(); - for (CTMLoadingContainer container : containerList) { - listBuilder.add(container.toProcessor(textureGetter)); - } - return listBuilder.build(); - } -} diff --git a/src/main/java/me/pepperbell/continuity/client/model/EmissiveUnbakedModel.java b/src/main/java/me/pepperbell/continuity/client/model/EmissiveUnbakedModel.java deleted file mode 100644 index f119f65d..00000000 --- a/src/main/java/me/pepperbell/continuity/client/model/EmissiveUnbakedModel.java +++ /dev/null @@ -1,28 +0,0 @@ -package me.pepperbell.continuity.client.model; - -import java.util.function.Function; - -import org.jetbrains.annotations.Nullable; - -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.ModelBakeSettings; -import net.minecraft.client.render.model.ModelLoader; -import net.minecraft.client.render.model.UnbakedModel; -import net.minecraft.client.texture.Sprite; -import net.minecraft.client.util.SpriteIdentifier; -import net.minecraft.util.Identifier; - -public class EmissiveUnbakedModel extends WrappingUnbakedModel { - public EmissiveUnbakedModel(UnbakedModel wrapped) { - super(wrapped); - } - - @Override - @Nullable - public BakedModel wrapBaked(@Nullable BakedModel bakedWrapped, ModelLoader loader, Function textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) { - if (bakedWrapped == null || bakedWrapped.isBuiltin()) { - return bakedWrapped; - } - return new EmissiveBakedModel(bakedWrapped); - } -} diff --git a/src/main/java/me/pepperbell/continuity/client/model/QuadProcessors.java b/src/main/java/me/pepperbell/continuity/client/model/QuadProcessors.java new file mode 100644 index 00000000..b5a390fc --- /dev/null +++ b/src/main/java/me/pepperbell/continuity/client/model/QuadProcessors.java @@ -0,0 +1,138 @@ +package me.pepperbell.continuity.client.model; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.locks.StampedLock; +import java.util.function.Function; + +import org.jetbrains.annotations.ApiStatus; + +import it.unimi.dsi.fastutil.Hash; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import me.pepperbell.continuity.api.client.CachingPredicates; +import me.pepperbell.continuity.api.client.QuadProcessor; +import net.minecraft.block.BlockState; +import net.minecraft.client.texture.Sprite; + +public final class QuadProcessors { + private static ProcessorHolder[] processorHolders = new ProcessorHolder[0]; + private static final BlockStateKeyCache CACHE = new BlockStateKeyCache(); + + public static Function getCache(BlockState state) { + return CACHE.apply(state); + } + + private static Slice computeSlice(BlockState state, Sprite sprite) { + List processorList = new ObjectArrayList<>(); + List multipassProcessorList = new ObjectArrayList<>(); + + for (ProcessorHolder holder : processorHolders) { + QuadProcessor processor = holder.processor(); + CachingPredicates predicates = holder.predicates(); + if (!predicates.affectsBlockStates() || predicates.affectsBlockState(state)) { + if (predicates.affectsSprites()) { + if (predicates.affectsSprite(sprite)) { + processorList.add(processor); + if (predicates.isValidForMultipass()) { + multipassProcessorList.add(processor); + } + } + } else { + processorList.add(processor); + } + } + } + + QuadProcessor[] processors = processorList.toArray(QuadProcessor[]::new); + QuadProcessor[] multipassProcessors = multipassProcessorList.toArray(QuadProcessor[]::new); + return new Slice(processors, multipassProcessors); + } + + @ApiStatus.Internal + public static void reload(List processorHolders) { + QuadProcessors.processorHolders = processorHolders.toArray(ProcessorHolder[]::new); + CACHE.clear(); + } + + public record ProcessorHolder(QuadProcessor processor, CachingPredicates predicates) { + } + + public record Slice(QuadProcessor[] processors, QuadProcessor[] multipassProcessors) { + } + + private static class BlockStateKeyCache implements Function { + private final Map map = new Object2ObjectOpenHashMap<>(); + private final StampedLock lock = new StampedLock(); + + @Override + public SpriteKeyCache apply(BlockState state) { + SpriteKeyCache innerCache; + long readStamp = lock.readLock(); + try { + innerCache = map.get(state); + } finally { + lock.unlockRead(readStamp); + } + if (innerCache == null) { + long writeStamp = lock.writeLock(); + try { + innerCache = new SpriteKeyCache(state); + map.put(state, innerCache); + } finally { + lock.unlockWrite(writeStamp); + } + } + return innerCache; + } + + public void clear() { + long writeStamp = lock.writeLock(); + try { + map.values().forEach(SpriteKeyCache::clear); + } finally { + lock.unlockWrite(writeStamp); + } + } + } + + private static class SpriteKeyCache implements Function { + private final Map map = new Object2ObjectOpenHashMap<>(4, Hash.FAST_LOAD_FACTOR); + private final StampedLock lock = new StampedLock(); + private final BlockState state; + + public SpriteKeyCache(BlockState state) { + this.state = state; + } + + @Override + public Slice apply(Sprite sprite) { + Slice slice; + long readStamp = lock.readLock(); + try { + slice = map.get(sprite); + } finally { + lock.unlockRead(readStamp); + } + if (slice == null) { + long writeStamp = lock.writeLock(); + try { + slice = computeSlice(state, sprite); + map.put(sprite, slice); + } finally { + lock.unlockWrite(writeStamp); + } + } + return slice; + } + + public void clear() { + long writeStamp = lock.writeLock(); + try { + map.clear(); + } finally { + lock.unlockWrite(writeStamp); + } + } + } +} diff --git a/src/main/java/me/pepperbell/continuity/client/model/WrappingUnbakedModel.java b/src/main/java/me/pepperbell/continuity/client/model/WrappingUnbakedModel.java deleted file mode 100644 index cc2bf190..00000000 --- a/src/main/java/me/pepperbell/continuity/client/model/WrappingUnbakedModel.java +++ /dev/null @@ -1,59 +0,0 @@ -package me.pepperbell.continuity.client.model; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; -import java.util.function.Function; - -import org.jetbrains.annotations.Nullable; - -import com.mojang.datafixers.util.Pair; - -import me.pepperbell.continuity.client.mixin.ModelLoaderAccessor; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.ModelBakeSettings; -import net.minecraft.client.render.model.ModelLoader; -import net.minecraft.client.render.model.UnbakedModel; -import net.minecraft.client.texture.Sprite; -import net.minecraft.client.util.SpriteIdentifier; -import net.minecraft.util.Identifier; - -public abstract class WrappingUnbakedModel implements UnbakedModel { - protected final UnbakedModel wrapped; - protected boolean isBaking; - - public WrappingUnbakedModel(UnbakedModel wrapped) { - this.wrapped = wrapped; - } - - @Override - public Collection getModelDependencies() { - return wrapped.getModelDependencies(); - } - - @Override - public Collection getTextureDependencies(Function unbakedModelGetter, Set> unresolvedTextureReferences) { - return wrapped.getTextureDependencies(unbakedModelGetter, unresolvedTextureReferences); - } - - @Override - @Nullable - public BakedModel bake(ModelLoader loader, Function textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) { - if (isBaking) { - return null; - } - isBaking = true; - - Map unbakedModels = ((ModelLoaderAccessor) loader).getUnbakedModels(); - UnbakedModel previous = unbakedModels.replace(modelId, wrapped); - BakedModel bakedWrapped = loader.bake(modelId, rotationContainer); - unbakedModels.replace(modelId, previous); - - BakedModel baked = wrapBaked(bakedWrapped, loader, textureGetter, rotationContainer, modelId); - isBaking = false; - return baked; - } - - @Nullable - public abstract BakedModel wrapBaked(@Nullable BakedModel bakedWrapped, ModelLoader loader, Function textureGetter, ModelBakeSettings rotationContainer, Identifier modelId); -} diff --git a/src/main/java/me/pepperbell/continuity/client/processor/AbstractQuadProcessor.java b/src/main/java/me/pepperbell/continuity/client/processor/AbstractQuadProcessor.java index dced780e..41afcaa0 100644 --- a/src/main/java/me/pepperbell/continuity/client/processor/AbstractQuadProcessor.java +++ b/src/main/java/me/pepperbell/continuity/client/processor/AbstractQuadProcessor.java @@ -20,12 +20,12 @@ public AbstractQuadProcessor(Sprite[] sprites, ProcessingPredicate processingPre } @Override - public ProcessingResult processQuad(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, int processorIndex, ProcessingContext context) { + public ProcessingResult processQuad(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, ProcessingContext context) { if (!processingPredicate.shouldProcessQuad(quad, sprite, blockView, state, pos, context)) { return ProcessingResult.CONTINUE; } - return processQuadInner(quad, sprite, blockView, state, pos, randomSupplier, pass, processorIndex, context); + return processQuadInner(quad, sprite, blockView, state, pos, randomSupplier, pass, context); } - public abstract ProcessingResult processQuadInner(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, int processorIndex, ProcessingContext context); + public abstract ProcessingResult processQuadInner(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, ProcessingContext context); } diff --git a/src/main/java/me/pepperbell/continuity/client/processor/BaseCachingPredicates.java b/src/main/java/me/pepperbell/continuity/client/processor/BaseCachingPredicates.java new file mode 100644 index 00000000..34452f3c --- /dev/null +++ b/src/main/java/me/pepperbell/continuity/client/processor/BaseCachingPredicates.java @@ -0,0 +1,73 @@ +package me.pepperbell.continuity.client.processor; + +import java.util.Set; +import java.util.function.Function; +import java.util.function.Predicate; + +import org.jetbrains.annotations.Nullable; + +import me.pepperbell.continuity.api.client.CachingPredicates; +import me.pepperbell.continuity.api.client.CachingPredicatesFactory; +import me.pepperbell.continuity.client.properties.BaseCTMProperties; +import net.minecraft.block.BlockState; +import net.minecraft.client.texture.Sprite; +import net.minecraft.client.util.SpriteIdentifier; +import net.minecraft.util.Identifier; + +public class BaseCachingPredicates implements CachingPredicates { + @Nullable + protected Set spriteIdSet; + @Nullable + protected Predicate blockStatePredicate; + protected boolean isValidForMultipass; + + public BaseCachingPredicates(@Nullable Set spriteIdSet, @Nullable Predicate blockStatePredicate, boolean isValidForMultipass) { + this.spriteIdSet = spriteIdSet; + this.blockStatePredicate = blockStatePredicate; + this.isValidForMultipass = isValidForMultipass; + } + + @Override + public boolean affectsSprites() { + return spriteIdSet != null; + } + + @Override + public boolean affectsSprite(Sprite sprite) { + if (spriteIdSet != null) { + return spriteIdSet.contains(sprite.getContents().getId()); + } + return false; + } + + @Override + public boolean affectsBlockStates() { + return blockStatePredicate != null; + } + + @Override + public boolean affectsBlockState(BlockState state) { + if (blockStatePredicate != null) { + return blockStatePredicate.test(state); + } + return false; + } + + @Override + public boolean isValidForMultipass() { + return isValidForMultipass; + } + + public static class Factory implements CachingPredicatesFactory { + protected boolean isValidForMultipass; + + public Factory(boolean isValidForMultipass) { + this.isValidForMultipass = isValidForMultipass; + } + + @Override + public CachingPredicates createPredicates(T properties, Function textureGetter) { + return new BaseCachingPredicates(properties.getMatchTilesSet(), properties.getMatchBlocksPredicate(), isValidForMultipass); + } + } +} diff --git a/src/main/java/me/pepperbell/continuity/client/processor/BaseProcessingPredicate.java b/src/main/java/me/pepperbell/continuity/client/processor/BaseProcessingPredicate.java index 5bafd499..b03df17d 100644 --- a/src/main/java/me/pepperbell/continuity/client/processor/BaseProcessingPredicate.java +++ b/src/main/java/me/pepperbell/continuity/client/processor/BaseProcessingPredicate.java @@ -1,7 +1,6 @@ package me.pepperbell.continuity.client.processor; import java.util.EnumSet; -import java.util.Set; import java.util.function.IntPredicate; import java.util.function.Predicate; @@ -15,7 +14,6 @@ import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.texture.Sprite; import net.minecraft.state.property.Properties; -import net.minecraft.util.Identifier; import net.minecraft.util.Nameable; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; @@ -23,14 +21,12 @@ import net.minecraft.world.biome.Biome; public class BaseProcessingPredicate implements ProcessingPredicate { - protected Set matchTilesSet; protected EnumSet faces; protected Predicate biomePredicate; protected IntPredicate heightPredicate; protected Predicate blockEntityNamePredicate; - public BaseProcessingPredicate(Set matchTilesSet, EnumSet faces, Predicate biomePredicate, IntPredicate heightPredicate, Predicate blockEntityNamePredicate) { - this.matchTilesSet = matchTilesSet; + public BaseProcessingPredicate(EnumSet faces, Predicate biomePredicate, IntPredicate heightPredicate, Predicate blockEntityNamePredicate) { this.faces = faces; this.biomePredicate = biomePredicate; this.heightPredicate = heightPredicate; @@ -39,11 +35,6 @@ public BaseProcessingPredicate(Set matchTilesSet, EnumSet @Override public boolean shouldProcessQuad(QuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, ProcessingDataProvider dataProvider) { - if (matchTilesSet != null) { - if (!matchTilesSet.contains(sprite.getId())) { - return false; - } - } if (heightPredicate != null) { if (!heightPredicate.test(pos.getY())) { return false; @@ -79,7 +70,7 @@ public boolean shouldProcessQuad(QuadView quad, Sprite sprite, BlockRenderView b } public static BaseProcessingPredicate fromProperties(BaseCTMProperties properties) { - return new BaseProcessingPredicate(properties.getMatchTilesSet(), properties.getFaces(), properties.getBiomePredicate(), properties.getHeightPredicate(), properties.getBlockEntityNamePredicate()); + return new BaseProcessingPredicate(properties.getFaces(), properties.getBiomePredicate(), properties.getHeightPredicate(), properties.getBlockEntityNamePredicate()); } public static class BiomeCache { diff --git a/src/main/java/me/pepperbell/continuity/client/processor/CompactCTMQuadProcessor.java b/src/main/java/me/pepperbell/continuity/client/processor/CompactCTMQuadProcessor.java index c7fef81f..78c601d8 100644 --- a/src/main/java/me/pepperbell/continuity/client/processor/CompactCTMQuadProcessor.java +++ b/src/main/java/me/pepperbell/continuity/client/processor/CompactCTMQuadProcessor.java @@ -62,7 +62,7 @@ public CompactCTMQuadProcessor(Sprite[] sprites, ProcessingPredicate processingP } @Override - public ProcessingResult processQuadInner(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, int processorIndex, ProcessingContext context) { + public ProcessingResult processQuadInner(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, ProcessingContext context) { int orientation = QuadUtil.getTextureOrientation(quad); Direction[] directions = DirectionMaps.getMap(quad.lightFace())[orientation]; BlockPos.Mutable mutablePos = context.getData(ProcessingDataKeys.MUTABLE_POS_KEY); diff --git a/src/main/java/me/pepperbell/continuity/client/processor/HorizontalQuadProcessor.java b/src/main/java/me/pepperbell/continuity/client/processor/HorizontalQuadProcessor.java index 1241bac7..dbb7cd5f 100644 --- a/src/main/java/me/pepperbell/continuity/client/processor/HorizontalQuadProcessor.java +++ b/src/main/java/me/pepperbell/continuity/client/processor/HorizontalQuadProcessor.java @@ -25,7 +25,7 @@ public HorizontalQuadProcessor(Sprite[] sprites, ProcessingPredicate processingP } @Override - public ProcessingResult processQuadInner(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, int processorIndex, ProcessingContext context) { + public ProcessingResult processQuadInner(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, ProcessingContext context) { Direction[] directions = DirectionMaps.getDirections(quad); BlockPos.Mutable mutablePos = context.getData(ProcessingDataKeys.MUTABLE_POS_KEY); int connections = getConnections(directions, mutablePos, blockView, state, pos, quad.lightFace(), sprite); diff --git a/src/main/java/me/pepperbell/continuity/client/processor/HorizontalVerticalQuadProcessor.java b/src/main/java/me/pepperbell/continuity/client/processor/HorizontalVerticalQuadProcessor.java index 4afe692c..446d3b86 100644 --- a/src/main/java/me/pepperbell/continuity/client/processor/HorizontalVerticalQuadProcessor.java +++ b/src/main/java/me/pepperbell/continuity/client/processor/HorizontalVerticalQuadProcessor.java @@ -30,7 +30,7 @@ public HorizontalVerticalQuadProcessor(Sprite[] sprites, ProcessingPredicate pro } @Override - public ProcessingResult processQuadInner(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, int processorIndex, ProcessingContext context) { + public ProcessingResult processQuadInner(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, ProcessingContext context) { Direction[] directions = DirectionMaps.getDirections(quad); BlockPos.Mutable mutablePos = context.getData(ProcessingDataKeys.MUTABLE_POS_KEY); int connections = getConnections(directions, mutablePos, blockView, state, pos, quad.lightFace(), sprite); diff --git a/src/main/java/me/pepperbell/continuity/client/processor/TopQuadProcessor.java b/src/main/java/me/pepperbell/continuity/client/processor/TopQuadProcessor.java index d4a0c453..34df6304 100644 --- a/src/main/java/me/pepperbell/continuity/client/processor/TopQuadProcessor.java +++ b/src/main/java/me/pepperbell/continuity/client/processor/TopQuadProcessor.java @@ -20,7 +20,7 @@ public TopQuadProcessor(Sprite[] sprites, ProcessingPredicate processingPredicat } @Override - public ProcessingResult processQuadInner(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, int processorIndex, ProcessingContext context) { + public ProcessingResult processQuadInner(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, ProcessingContext context) { Direction lightFace = quad.lightFace(); Direction.Axis axis; if (state.contains(Properties.AXIS)) { diff --git a/src/main/java/me/pepperbell/continuity/client/processor/VerticalHorizontalQuadProcessor.java b/src/main/java/me/pepperbell/continuity/client/processor/VerticalHorizontalQuadProcessor.java index fbe50031..3a7a8dd9 100644 --- a/src/main/java/me/pepperbell/continuity/client/processor/VerticalHorizontalQuadProcessor.java +++ b/src/main/java/me/pepperbell/continuity/client/processor/VerticalHorizontalQuadProcessor.java @@ -30,7 +30,7 @@ public VerticalHorizontalQuadProcessor(Sprite[] sprites, ProcessingPredicate pro } @Override - public ProcessingResult processQuadInner(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, int processorIndex, ProcessingContext context) { + public ProcessingResult processQuadInner(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, ProcessingContext context) { Direction[] directions = DirectionMaps.getDirections(quad); BlockPos.Mutable mutablePos = context.getData(ProcessingDataKeys.MUTABLE_POS_KEY); int connections = getConnections(directions, mutablePos, blockView, state, pos, quad.lightFace(), sprite); diff --git a/src/main/java/me/pepperbell/continuity/client/processor/VerticalQuadProcessor.java b/src/main/java/me/pepperbell/continuity/client/processor/VerticalQuadProcessor.java index 2cf5e211..45ca8954 100644 --- a/src/main/java/me/pepperbell/continuity/client/processor/VerticalQuadProcessor.java +++ b/src/main/java/me/pepperbell/continuity/client/processor/VerticalQuadProcessor.java @@ -27,7 +27,7 @@ public VerticalQuadProcessor(Sprite[] sprites, ProcessingPredicate processingPre } @Override - public ProcessingResult processQuadInner(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, int processorIndex, ProcessingContext context) { + public ProcessingResult processQuadInner(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, ProcessingContext context) { Direction[] directions = DirectionMaps.getDirections(quad); BlockPos.Mutable mutablePos = context.getData(ProcessingDataKeys.MUTABLE_POS_KEY); int connections = getConnections(directions, mutablePos, blockView, state, pos, quad.lightFace(), sprite); diff --git a/src/main/java/me/pepperbell/continuity/client/processor/overlay/OverlayProcessingPredicate.java b/src/main/java/me/pepperbell/continuity/client/processor/overlay/OverlayProcessingPredicate.java index bfb7a9b3..e45ac410 100644 --- a/src/main/java/me/pepperbell/continuity/client/processor/overlay/OverlayProcessingPredicate.java +++ b/src/main/java/me/pepperbell/continuity/client/processor/overlay/OverlayProcessingPredicate.java @@ -1,7 +1,6 @@ package me.pepperbell.continuity.client.processor.overlay; import java.util.EnumSet; -import java.util.Set; import java.util.function.IntPredicate; import java.util.function.Predicate; @@ -12,15 +11,14 @@ import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; import net.minecraft.block.BlockState; import net.minecraft.client.texture.Sprite; -import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.BlockRenderView; import net.minecraft.world.biome.Biome; public class OverlayProcessingPredicate extends BaseProcessingPredicate { - public OverlayProcessingPredicate(Set matchTilesSet, EnumSet faces, Predicate biomePredicate, IntPredicate heightPredicate, Predicate blockEntityNamePredicate) { - super(matchTilesSet, faces, biomePredicate, heightPredicate, blockEntityNamePredicate); + public OverlayProcessingPredicate(EnumSet faces, Predicate biomePredicate, IntPredicate heightPredicate, Predicate blockEntityNamePredicate) { + super(faces, biomePredicate, heightPredicate, blockEntityNamePredicate); } @Override @@ -32,6 +30,6 @@ public boolean shouldProcessQuad(QuadView quad, Sprite sprite, BlockRenderView b } public static OverlayProcessingPredicate fromProperties(BaseCTMProperties properties) { - return new OverlayProcessingPredicate(properties.getMatchTilesSet(), properties.getFaces(), properties.getBiomePredicate(), properties.getHeightPredicate(), properties.getBlockEntityNamePredicate()); + return new OverlayProcessingPredicate(properties.getFaces(), properties.getBiomePredicate(), properties.getHeightPredicate(), properties.getBlockEntityNamePredicate()); } } diff --git a/src/main/java/me/pepperbell/continuity/client/processor/overlay/SimpleOverlayQuadProcessor.java b/src/main/java/me/pepperbell/continuity/client/processor/overlay/SimpleOverlayQuadProcessor.java index 76f8e3d5..d1b754f3 100644 --- a/src/main/java/me/pepperbell/continuity/client/processor/overlay/SimpleOverlayQuadProcessor.java +++ b/src/main/java/me/pepperbell/continuity/client/processor/overlay/SimpleOverlayQuadProcessor.java @@ -39,7 +39,7 @@ public SimpleOverlayQuadProcessor(SpriteProvider spriteProvider, ProcessingPredi } @Override - public ProcessingResult processQuad(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, int processorIndex, ProcessingContext context) { + public ProcessingResult processQuad(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, ProcessingContext context) { if (processingPredicate.shouldProcessQuad(quad, sprite, blockView, state, pos, context)) { Sprite newSprite = spriteProvider.getSprite(quad, sprite, blockView, state, pos, randomSupplier, context); if (!TextureUtil.isMissingSprite(newSprite)) { diff --git a/src/main/java/me/pepperbell/continuity/client/processor/overlay/StandardOverlayQuadProcessor.java b/src/main/java/me/pepperbell/continuity/client/processor/overlay/StandardOverlayQuadProcessor.java index 291c1d1d..ea07e101 100644 --- a/src/main/java/me/pepperbell/continuity/client/processor/overlay/StandardOverlayQuadProcessor.java +++ b/src/main/java/me/pepperbell/continuity/client/processor/overlay/StandardOverlayQuadProcessor.java @@ -59,7 +59,7 @@ public StandardOverlayQuadProcessor(Sprite[] sprites, ProcessingPredicate proces } @Override - public ProcessingResult processQuadInner(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, int processorIndex, ProcessingContext context) { + public ProcessingResult processQuadInner(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, ProcessingContext context) { Direction lightFace = quad.lightFace(); OverlayRenderer renderer = getRenderer(blockView, pos, state, lightFace, sprite, DirectionMaps.getMap(lightFace)[0], context); if (renderer != null) { @@ -81,7 +81,7 @@ protected boolean appliesOverlay(BlockState other, BlockRenderView blockView, Bl } } if (connectTilesSet != null) { - if (!connectTilesSet.contains(SpriteCalculator.getSprite(other, face).getId())) { + if (!connectTilesSet.contains(SpriteCalculator.getSprite(other, face).getContents().getId())) { return false; } } @@ -95,7 +95,7 @@ protected boolean hasSameOverlay(BlockState other, BlockRenderView blockView, Bl } } if (matchTilesSet != null) { - if (!matchTilesSet.contains(SpriteCalculator.getSprite(other, face).getId())) { + if (!matchTilesSet.contains(SpriteCalculator.getSprite(other, face).getContents().getId())) { return false; } } diff --git a/src/main/java/me/pepperbell/continuity/client/processor/simple/SimpleQuadProcessor.java b/src/main/java/me/pepperbell/continuity/client/processor/simple/SimpleQuadProcessor.java index 5b99c235..436e14c8 100644 --- a/src/main/java/me/pepperbell/continuity/client/processor/simple/SimpleQuadProcessor.java +++ b/src/main/java/me/pepperbell/continuity/client/processor/simple/SimpleQuadProcessor.java @@ -26,7 +26,7 @@ public SimpleQuadProcessor(SpriteProvider spriteProvider, ProcessingPredicate pr } @Override - public ProcessingResult processQuad(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, int processorIndex, ProcessingContext context) { + public ProcessingResult processQuad(MutableQuadView quad, Sprite sprite, BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, int pass, ProcessingContext context) { if (!processingPredicate.shouldProcessQuad(quad, sprite, blockView, state, pos, context)) { return ProcessingResult.CONTINUE; } diff --git a/src/main/java/me/pepperbell/continuity/client/properties/BaseCTMProperties.java b/src/main/java/me/pepperbell/continuity/client/properties/BaseCTMProperties.java index 4dac6f92..632f368c 100644 --- a/src/main/java/me/pepperbell/continuity/client/properties/BaseCTMProperties.java +++ b/src/main/java/me/pepperbell/continuity/client/properties/BaseCTMProperties.java @@ -4,6 +4,7 @@ import java.util.EnumSet; import java.util.List; import java.util.Locale; +import java.util.Optional; import java.util.Properties; import java.util.Set; import java.util.function.IntPredicate; @@ -23,7 +24,6 @@ import me.pepperbell.continuity.api.client.CTMProperties; import me.pepperbell.continuity.api.client.CTMPropertiesFactory; import me.pepperbell.continuity.client.ContinuityClient; -import me.pepperbell.continuity.client.resource.ResourcePackUtil; import me.pepperbell.continuity.client.resource.ResourceRedirectHandler; import me.pepperbell.continuity.client.util.MathUtil; import me.pepperbell.continuity.client.util.TextureUtil; @@ -32,13 +32,16 @@ import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.util.SpriteIdentifier; +import net.minecraft.registry.Registries; import net.minecraft.resource.DefaultResourcePack; +import net.minecraft.resource.Resource; +import net.minecraft.resource.ResourceManager; import net.minecraft.resource.ResourcePack; import net.minecraft.util.Identifier; import net.minecraft.util.InvalidIdentifierException; import net.minecraft.util.math.Direction; -import net.minecraft.util.registry.Registry; import net.minecraft.world.biome.Biome; public class BaseCTMProperties implements CTMProperties { @@ -53,6 +56,7 @@ public class BaseCTMProperties implements CTMProperties { protected Identifier id; protected String packName; protected int packPriority; + protected ResourceManager resourceManager; protected String method; protected Set matchTilesSet; @@ -69,40 +73,15 @@ public class BaseCTMProperties implements CTMProperties { protected Set textureDependencies; protected List spriteIds; - public BaseCTMProperties(Properties properties, Identifier id, String packName, int packPriority, String method) { + public BaseCTMProperties(Properties properties, Identifier id, ResourcePack pack, int packPriority, ResourceManager resourceManager, String method) { this.properties = properties; this.id = id; - this.packName = packName; + this.packName = pack.getName(); this.packPriority = packPriority; + this.resourceManager = resourceManager; this.method = method; } - @Override - public boolean affectsTextures() { - return matchTilesSet != null; - } - - @Override - public boolean affectsTexture(Identifier id) { - if (matchTilesSet != null) { - return matchTilesSet.contains(id); - } - return false; - } - - @Override - public boolean affectsBlockStates() { - return matchBlocksPredicate != null; - } - - @Override - public boolean affectsBlockState(BlockState state) { - if (matchBlocksPredicate != null) { - return matchBlocksPredicate.test(state); - } - return false; - } - @Override public Set getTextureDependencies() { if (textureDependencies == null) { @@ -151,7 +130,7 @@ public void init() { } protected void parseMatchTiles() { - matchTilesSet = PropertiesParsingHelper.parseMatchTiles(properties, "matchTiles", id, packName); + matchTilesSet = PropertiesParsingHelper.parseMatchTiles(properties, "matchTiles", id, packName, ResourceRedirectHandler.get(resourceManager)); if (matchTilesSet != null && matchTilesSet.isEmpty()) { valid = false; } @@ -170,7 +149,7 @@ protected void detectMatches() { if (baseName.startsWith("block_")) { try { Identifier id = new Identifier(baseName.substring(6)); - Block block = Registry.BLOCK.get(id); + Block block = Registries.BLOCK.get(id); if (block != Blocks.AIR) { matchBlocksPredicate = state -> state.getBlock() == block; } @@ -252,8 +231,12 @@ protected void parseTiles() { } else if (!path.startsWith("textures/") && !path.startsWith("optifine/")) { path = basePath + path; } - if (path.startsWith("optifine/") && namespace == null) { - namespace = id.getNamespace(); + if (namespace == null) { + if (path.startsWith("optifine/")) { + namespace = id.getNamespace(); + } else { + namespace = Identifier.DEFAULT_NAMESPACE; + } } try { @@ -553,7 +536,7 @@ protected void parseName() { protected void parsePrioritize() { String prioritizeStr = properties.getProperty("prioritize"); if (prioritizeStr == null) { - prioritized = affectsTextures(); + prioritized = matchTilesSet != null; return; } @@ -568,7 +551,7 @@ protected void parseResourceCondition() { String[] conditionStrs = conditionsStr.trim().split("\\|"); if (conditionStrs.length != 0) { - DefaultResourcePack defaultPack = ResourcePackUtil.getDefaultResourcePack(); + DefaultResourcePack defaultPack = MinecraftClient.getInstance().getDefaultResourcePack(); for (int i = 0; i < conditionStrs.length; i++) { String conditionStr = conditionStrs[i]; @@ -592,14 +575,14 @@ protected void parseResourceCondition() { } if (packStr == null || packStr.equals("default")) { - ResourcePack pack = ResourcePackUtil.getProvidingResourcePack(resourceId); - if (pack != null && pack != defaultPack) { + Optional optionalResource = resourceManager.getResource(resourceId); + if (optionalResource.isPresent() && optionalResource.get().getPack() != defaultPack) { valid = false; break; } } else if (packStr.equals("programmer_art")) { - ResourcePack pack = ResourcePackUtil.getProvidingResourcePack(resourceId); - if (pack != null && !pack.getName().equals("Programmer Art")) { + Optional optionalResource = resourceManager.getResource(resourceId); + if (optionalResource.isPresent() && !optionalResource.get().getPack().getName().equals("programmer_art")) { valid = false; break; } @@ -619,7 +602,7 @@ protected boolean isValid() { protected void resolveTiles() { textureDependencies = new ObjectOpenHashSet<>(); spriteIds = new ObjectArrayList<>(); - ResourceRedirectHandler redirectHandler = ResourceRedirectHandler.get(); + ResourceRedirectHandler redirectHandler = ResourceRedirectHandler.get(resourceManager); for (Identifier tile : tiles) { SpriteIdentifier spriteId; @@ -711,8 +694,8 @@ public List getSpriteIds() { } public static CTMPropertiesFactory wrapFactory(CTMPropertiesFactory factory) { - return (properties, id, packName, packPriority, method) -> { - T ctmProperties = factory.createProperties(properties, id, packName, packPriority, method); + return (properties, id, pack, packPriority, resourceManager, method) -> { + T ctmProperties = factory.createProperties(properties, id, pack, packPriority, resourceManager, method); if (ctmProperties == null) { return null; } diff --git a/src/main/java/me/pepperbell/continuity/client/properties/CompactConnectingCTMProperties.java b/src/main/java/me/pepperbell/continuity/client/properties/CompactConnectingCTMProperties.java index 26051f99..b1b052bc 100644 --- a/src/main/java/me/pepperbell/continuity/client/properties/CompactConnectingCTMProperties.java +++ b/src/main/java/me/pepperbell/continuity/client/properties/CompactConnectingCTMProperties.java @@ -5,13 +5,15 @@ import it.unimi.dsi.fastutil.ints.Int2IntArrayMap; import it.unimi.dsi.fastutil.ints.Int2IntMap; import me.pepperbell.continuity.client.ContinuityClient; +import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.ResourcePack; import net.minecraft.util.Identifier; public class CompactConnectingCTMProperties extends StandardConnectingCTMProperties { protected Int2IntMap tileReplacementMap; - public CompactConnectingCTMProperties(Properties properties, Identifier id, String packName, int packPriority, String method) { - super(properties, id, packName, packPriority, method); + public CompactConnectingCTMProperties(Properties properties, Identifier id, ResourcePack pack, int packPriority, ResourceManager resourceManager, String method) { + super(properties, id, pack, packPriority, resourceManager, method); } @Override @@ -56,11 +58,6 @@ protected void parseTileReplacements() { } } - @Override - public boolean isValidForMultipass() { - return false; - } - public Int2IntMap getTileReplacementMap() { return tileReplacementMap; } diff --git a/src/main/java/me/pepperbell/continuity/client/properties/ConnectingCTMProperties.java b/src/main/java/me/pepperbell/continuity/client/properties/ConnectingCTMProperties.java index 9dcbb331..11ff62bf 100644 --- a/src/main/java/me/pepperbell/continuity/client/properties/ConnectingCTMProperties.java +++ b/src/main/java/me/pepperbell/continuity/client/properties/ConnectingCTMProperties.java @@ -8,6 +8,8 @@ import me.pepperbell.continuity.client.util.SpriteCalculator; import net.minecraft.block.BlockState; import net.minecraft.client.texture.Sprite; +import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.ResourcePack; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; @@ -16,8 +18,8 @@ public class ConnectingCTMProperties extends BaseCTMProperties { protected ConnectionPredicate connectionPredicate; - public ConnectingCTMProperties(Properties properties, Identifier id, String packName, int packPriority, String method) { - super(properties, id, packName, packPriority, method); + public ConnectingCTMProperties(Properties properties, Identifier id, ResourcePack pack, int packPriority, ResourceManager resourceManager, String method) { + super(properties, id, pack, packPriority, resourceManager, method); } @Override @@ -43,9 +45,9 @@ protected void parseConnect() { protected void detectConnect() { if (connectionPredicate == null) { - if (affectsBlockStates()) { + if (matchBlocksPredicate != null) { connectionPredicate = ConnectionType.BLOCK; - } else if (affectsTextures()) { + } else if (matchTilesSet != null) { connectionPredicate = ConnectionType.TILE; } } diff --git a/src/main/java/me/pepperbell/continuity/client/properties/PropertiesParsingHelper.java b/src/main/java/me/pepperbell/continuity/client/properties/PropertiesParsingHelper.java index ba10e46b..870e60a2 100644 --- a/src/main/java/me/pepperbell/continuity/client/properties/PropertiesParsingHelper.java +++ b/src/main/java/me/pepperbell/continuity/client/properties/PropertiesParsingHelper.java @@ -20,16 +20,16 @@ import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; +import net.minecraft.registry.Registries; import net.minecraft.state.property.Property; import net.minecraft.util.Identifier; import net.minecraft.util.InvalidIdentifierException; -import net.minecraft.util.registry.Registry; public final class PropertiesParsingHelper { public static final Predicate EMPTY_BLOCK_STATE_PREDICATE = state -> false; @Nullable - public static ImmutableSet parseMatchTiles(Properties properties, String propertyKey, Identifier fileLocation, String packName) { + public static ImmutableSet parseMatchTiles(Properties properties, String propertyKey, Identifier fileLocation, String packName, @Nullable ResourceRedirectHandler redirectHandler) { String matchTilesStr = properties.getProperty(propertyKey); if (matchTilesStr == null) { return null; @@ -38,7 +38,6 @@ public static ImmutableSet parseMatchTiles(Properties properties, St String[] matchTileStrs = matchTilesStr.trim().split(" "); if (matchTileStrs.length != 0) { String basePath = FilenameUtils.getPath(fileLocation.getPath()); - ResourceRedirectHandler redirectHandler = ResourceRedirectHandler.get(); ImmutableSet.Builder setBuilder = ImmutableSet.builder(); for (int i = 0; i < matchTileStrs.length; i++) { @@ -79,6 +78,9 @@ public static ImmutableSet parseMatchTiles(Properties properties, St namespace = fileLocation.getNamespace(); } } + if (namespace == null) { + namespace = Identifier.DEFAULT_NAMESPACE; + } try { setBuilder.add(new Identifier(namespace, path)); @@ -128,7 +130,7 @@ public static Predicate parseBlockStates(Properties properties, Stri continue; } - Block block = Registry.BLOCK.get(blockId); + Block block = Registries.BLOCK.get(blockId); if (block != Blocks.AIR) { if (parts.length > startIndex) { ImmutableMap.Builder, Comparable[]> propertyMapBuilder = ImmutableMap.builder(); diff --git a/src/main/java/me/pepperbell/continuity/client/properties/RandomCTMProperties.java b/src/main/java/me/pepperbell/continuity/client/properties/RandomCTMProperties.java index e67f9e20..ae64a2aa 100644 --- a/src/main/java/me/pepperbell/continuity/client/properties/RandomCTMProperties.java +++ b/src/main/java/me/pepperbell/continuity/client/properties/RandomCTMProperties.java @@ -7,6 +7,8 @@ import me.pepperbell.continuity.client.ContinuityClient; import me.pepperbell.continuity.client.processor.Symmetry; import me.pepperbell.continuity.client.util.RandomIndexProvider; +import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.ResourcePack; import net.minecraft.util.Identifier; public class RandomCTMProperties extends BaseCTMProperties { @@ -15,8 +17,8 @@ public class RandomCTMProperties extends BaseCTMProperties { protected Symmetry symmetry = Symmetry.NONE; protected boolean linked = false; - public RandomCTMProperties(Properties properties, Identifier id, String packName, int packPriority, String method) { - super(properties, id, packName, packPriority, method); + public RandomCTMProperties(Properties properties, Identifier id, ResourcePack pack, int packPriority, ResourceManager resourceManager, String method) { + super(properties, id, pack, packPriority, resourceManager, method); } @Override diff --git a/src/main/java/me/pepperbell/continuity/client/properties/RepeatCTMProperties.java b/src/main/java/me/pepperbell/continuity/client/properties/RepeatCTMProperties.java index 3a7a1533..a97f5b93 100644 --- a/src/main/java/me/pepperbell/continuity/client/properties/RepeatCTMProperties.java +++ b/src/main/java/me/pepperbell/continuity/client/properties/RepeatCTMProperties.java @@ -4,6 +4,8 @@ import me.pepperbell.continuity.client.ContinuityClient; import me.pepperbell.continuity.client.processor.Symmetry; +import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.ResourcePack; import net.minecraft.util.Identifier; public class RepeatCTMProperties extends BaseCTMProperties { @@ -11,8 +13,8 @@ public class RepeatCTMProperties extends BaseCTMProperties { protected int height; protected Symmetry symmetry = Symmetry.NONE; - public RepeatCTMProperties(Properties properties, Identifier id, String packName, int packPriority, String method) { - super(properties, id, packName, packPriority, method); + public RepeatCTMProperties(Properties properties, Identifier id, ResourcePack pack, int packPriority, ResourceManager resourceManager, String method) { + super(properties, id, pack, packPriority, resourceManager, method); } @Override diff --git a/src/main/java/me/pepperbell/continuity/client/properties/StandardConnectingCTMProperties.java b/src/main/java/me/pepperbell/continuity/client/properties/StandardConnectingCTMProperties.java index 6ad1a07b..8d2cd17a 100644 --- a/src/main/java/me/pepperbell/continuity/client/properties/StandardConnectingCTMProperties.java +++ b/src/main/java/me/pepperbell/continuity/client/properties/StandardConnectingCTMProperties.java @@ -2,13 +2,15 @@ import java.util.Properties; +import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.ResourcePack; import net.minecraft.util.Identifier; public class StandardConnectingCTMProperties extends ConnectingCTMProperties { protected boolean innerSeams = false; - public StandardConnectingCTMProperties(Properties properties, Identifier id, String packName, int packPriority, String method) { - super(properties, id, packName, packPriority, method); + public StandardConnectingCTMProperties(Properties properties, Identifier id, ResourcePack pack, int packPriority, ResourceManager resourceManager, String method) { + super(properties, id, pack, packPriority, resourceManager, method); } @Override diff --git a/src/main/java/me/pepperbell/continuity/client/properties/TileAmountValidator.java b/src/main/java/me/pepperbell/continuity/client/properties/TileAmountValidator.java index 3a443eb7..0506f836 100644 --- a/src/main/java/me/pepperbell/continuity/client/properties/TileAmountValidator.java +++ b/src/main/java/me/pepperbell/continuity/client/properties/TileAmountValidator.java @@ -7,8 +7,8 @@ public interface TileAmountValidator { boolean validateTileAmount(int amount, T properties); static CTMPropertiesFactory wrapFactory(CTMPropertiesFactory factory, TileAmountValidator validator) { - return (properties, id, packName, packPriority, method) -> { - T ctmProperties = factory.createProperties(properties, id, packName, packPriority, method); + return (properties, id, pack, packPriority, resourceManager, method) -> { + T ctmProperties = factory.createProperties(properties, id, pack, packPriority, resourceManager, method); if (ctmProperties == null) { return null; } diff --git a/src/main/java/me/pepperbell/continuity/client/properties/overlay/BaseOverlayCTMProperties.java b/src/main/java/me/pepperbell/continuity/client/properties/overlay/BaseOverlayCTMProperties.java index cd55aca5..09cdd647 100644 --- a/src/main/java/me/pepperbell/continuity/client/properties/overlay/BaseOverlayCTMProperties.java +++ b/src/main/java/me/pepperbell/continuity/client/properties/overlay/BaseOverlayCTMProperties.java @@ -3,13 +3,15 @@ import java.util.Properties; import me.pepperbell.continuity.client.properties.BaseCTMProperties; +import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.ResourcePack; import net.minecraft.util.Identifier; public class BaseOverlayCTMProperties extends BaseCTMProperties implements OverlayPropertiesSection.Provider { protected OverlayPropertiesSection overlaySection; - public BaseOverlayCTMProperties(Properties properties, Identifier id, String packName, int packPriority, String method) { - super(properties, id, packName, packPriority, method); + public BaseOverlayCTMProperties(Properties properties, Identifier id, ResourcePack pack, int packPriority, ResourceManager resourceManager, String method) { + super(properties, id, pack, packPriority, resourceManager, method); overlaySection = new OverlayPropertiesSection(properties, id, packName); } diff --git a/src/main/java/me/pepperbell/continuity/client/properties/overlay/OverlayPropertiesSection.java b/src/main/java/me/pepperbell/continuity/client/properties/overlay/OverlayPropertiesSection.java index e369f8e9..8377cb26 100644 --- a/src/main/java/me/pepperbell/continuity/client/properties/overlay/OverlayPropertiesSection.java +++ b/src/main/java/me/pepperbell/continuity/client/properties/overlay/OverlayPropertiesSection.java @@ -8,9 +8,9 @@ import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; +import net.minecraft.registry.Registries; import net.minecraft.util.Identifier; import net.minecraft.util.InvalidIdentifierException; -import net.minecraft.util.registry.Registry; public class OverlayPropertiesSection { protected Properties properties; @@ -71,7 +71,7 @@ protected void parseTintBlock() { return; } - Block block = Registry.BLOCK.get(blockId); + Block block = Registries.BLOCK.get(blockId); if (block != Blocks.AIR) { tintBlock = block.getDefaultState(); } else { diff --git a/src/main/java/me/pepperbell/continuity/client/properties/overlay/RandomOverlayCTMProperties.java b/src/main/java/me/pepperbell/continuity/client/properties/overlay/RandomOverlayCTMProperties.java index 40581554..1faaa675 100644 --- a/src/main/java/me/pepperbell/continuity/client/properties/overlay/RandomOverlayCTMProperties.java +++ b/src/main/java/me/pepperbell/continuity/client/properties/overlay/RandomOverlayCTMProperties.java @@ -3,13 +3,15 @@ import java.util.Properties; import me.pepperbell.continuity.client.properties.RandomCTMProperties; +import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.ResourcePack; import net.minecraft.util.Identifier; public class RandomOverlayCTMProperties extends RandomCTMProperties implements OverlayPropertiesSection.Provider { protected OverlayPropertiesSection overlaySection; - public RandomOverlayCTMProperties(Properties properties, Identifier id, String packName, int packPriority, String method) { - super(properties, id, packName, packPriority, method); + public RandomOverlayCTMProperties(Properties properties, Identifier id, ResourcePack pack, int packPriority, ResourceManager resourceManager, String method) { + super(properties, id, pack, packPriority, resourceManager, method); overlaySection = new OverlayPropertiesSection(properties, id, packName); } diff --git a/src/main/java/me/pepperbell/continuity/client/properties/overlay/RepeatOverlayCTMProperties.java b/src/main/java/me/pepperbell/continuity/client/properties/overlay/RepeatOverlayCTMProperties.java index 0feb2781..fce778c9 100644 --- a/src/main/java/me/pepperbell/continuity/client/properties/overlay/RepeatOverlayCTMProperties.java +++ b/src/main/java/me/pepperbell/continuity/client/properties/overlay/RepeatOverlayCTMProperties.java @@ -3,13 +3,15 @@ import java.util.Properties; import me.pepperbell.continuity.client.properties.RepeatCTMProperties; +import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.ResourcePack; import net.minecraft.util.Identifier; public class RepeatOverlayCTMProperties extends RepeatCTMProperties implements OverlayPropertiesSection.Provider { protected OverlayPropertiesSection overlaySection; - public RepeatOverlayCTMProperties(Properties properties, Identifier id, String packName, int packPriority, String method) { - super(properties, id, packName, packPriority, method); + public RepeatOverlayCTMProperties(Properties properties, Identifier id, ResourcePack pack, int packPriority, ResourceManager resourceManager, String method) { + super(properties, id, pack, packPriority, resourceManager, method); overlaySection = new OverlayPropertiesSection(properties, id, packName); } diff --git a/src/main/java/me/pepperbell/continuity/client/properties/overlay/StandardConnectingOverlayCTMProperties.java b/src/main/java/me/pepperbell/continuity/client/properties/overlay/StandardConnectingOverlayCTMProperties.java index 5889ccc9..34001415 100644 --- a/src/main/java/me/pepperbell/continuity/client/properties/overlay/StandardConnectingOverlayCTMProperties.java +++ b/src/main/java/me/pepperbell/continuity/client/properties/overlay/StandardConnectingOverlayCTMProperties.java @@ -3,13 +3,15 @@ import java.util.Properties; import me.pepperbell.continuity.client.properties.StandardConnectingCTMProperties; +import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.ResourcePack; import net.minecraft.util.Identifier; public class StandardConnectingOverlayCTMProperties extends StandardConnectingCTMProperties implements OverlayPropertiesSection.Provider { protected OverlayPropertiesSection overlaySection; - public StandardConnectingOverlayCTMProperties(Properties properties, Identifier id, String packName, int packPriority, String method) { - super(properties, id, packName, packPriority, method); + public StandardConnectingOverlayCTMProperties(Properties properties, Identifier id, ResourcePack pack, int packPriority, ResourceManager resourceManager, String method) { + super(properties, id, pack, packPriority, resourceManager, method); overlaySection = new OverlayPropertiesSection(properties, id, packName); } diff --git a/src/main/java/me/pepperbell/continuity/client/properties/overlay/StandardOverlayCTMProperties.java b/src/main/java/me/pepperbell/continuity/client/properties/overlay/StandardOverlayCTMProperties.java index b7116c92..e3c3afe9 100644 --- a/src/main/java/me/pepperbell/continuity/client/properties/overlay/StandardOverlayCTMProperties.java +++ b/src/main/java/me/pepperbell/continuity/client/properties/overlay/StandardOverlayCTMProperties.java @@ -6,7 +6,10 @@ import me.pepperbell.continuity.client.properties.ConnectingCTMProperties; import me.pepperbell.continuity.client.properties.PropertiesParsingHelper; +import me.pepperbell.continuity.client.resource.ResourceRedirectHandler; import net.minecraft.block.BlockState; +import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.ResourcePack; import net.minecraft.util.Identifier; public class StandardOverlayCTMProperties extends ConnectingCTMProperties implements OverlayPropertiesSection.Provider { @@ -14,8 +17,8 @@ public class StandardOverlayCTMProperties extends ConnectingCTMProperties implem protected Set connectTilesSet; protected Predicate connectBlocksPredicate; - public StandardOverlayCTMProperties(Properties properties, Identifier id, String packName, int packPriority, String method) { - super(properties, id, packName, packPriority, method); + public StandardOverlayCTMProperties(Properties properties, Identifier id, ResourcePack pack, int packPriority, ResourceManager resourceManager, String method) { + super(properties, id, pack, packPriority, resourceManager, method); overlaySection = new OverlayPropertiesSection(properties, id, packName); } @@ -33,7 +36,7 @@ public OverlayPropertiesSection getOverlayPropertiesSection() { } protected void parseConnectTiles() { - connectTilesSet = PropertiesParsingHelper.parseMatchTiles(properties, "connectTiles", id, packName); + connectTilesSet = PropertiesParsingHelper.parseMatchTiles(properties, "connectTiles", id, packName, ResourceRedirectHandler.get(resourceManager)); } protected void parseConnectBlocks() { diff --git a/src/main/java/me/pepperbell/continuity/client/resource/AtlasLoaderInitContext.java b/src/main/java/me/pepperbell/continuity/client/resource/AtlasLoaderInitContext.java new file mode 100644 index 00000000..6c5e6eea --- /dev/null +++ b/src/main/java/me/pepperbell/continuity/client/resource/AtlasLoaderInitContext.java @@ -0,0 +1,14 @@ +package me.pepperbell.continuity.client.resource; + +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.util.Identifier; + +public interface AtlasLoaderInitContext { + ThreadLocal THREAD_LOCAL = new ThreadLocal<>(); + + CompletableFuture<@Nullable Set> getExtraIdsFuture(); +} diff --git a/src/main/java/me/pepperbell/continuity/client/resource/AtlasLoaderLoadContext.java b/src/main/java/me/pepperbell/continuity/client/resource/AtlasLoaderLoadContext.java new file mode 100644 index 00000000..4ef8685f --- /dev/null +++ b/src/main/java/me/pepperbell/continuity/client/resource/AtlasLoaderLoadContext.java @@ -0,0 +1,13 @@ +package me.pepperbell.continuity.client.resource; + +import java.util.Map; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.util.Identifier; + +public interface AtlasLoaderLoadContext { + ThreadLocal THREAD_LOCAL = new ThreadLocal<>(); + + void setEmissiveIdMap(@Nullable Map map); +} diff --git a/src/main/java/me/pepperbell/continuity/client/resource/BakedModelManagerReloadExtension.java b/src/main/java/me/pepperbell/continuity/client/resource/BakedModelManagerReloadExtension.java new file mode 100644 index 00000000..75f744d5 --- /dev/null +++ b/src/main/java/me/pepperbell/continuity/client/resource/BakedModelManagerReloadExtension.java @@ -0,0 +1,96 @@ +package me.pepperbell.continuity.client.resource; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +import org.jetbrains.annotations.Nullable; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import me.pepperbell.continuity.client.mixinterface.ModelLoaderExtension; +import me.pepperbell.continuity.client.model.QuadProcessors; +import net.minecraft.client.render.model.ModelLoader; +import net.minecraft.client.render.model.SpriteAtlasManager; +import net.minecraft.client.texture.Sprite; +import net.minecraft.client.texture.SpriteAtlasTexture; +import net.minecraft.resource.ResourceManager; +import net.minecraft.util.Identifier; + +public class BakedModelManagerReloadExtension { + private final CompletableFuture ctmLoadingResultFuture; + private final AtomicBoolean wrapEmissiveModels = new AtomicBoolean(); + private volatile List processorHolders; + + public BakedModelManagerReloadExtension(ResourceManager resourceManager, Executor prepareExecutor) { + ctmLoadingResultFuture = CompletableFuture.supplyAsync(() -> CTMPropertiesLoader.loadAllWithState(resourceManager), prepareExecutor); + EmissiveSuffixLoader.load(resourceManager); + } + + public void setContext() { + SpriteLoaderLoadContext.THREAD_LOCAL.set(new SpriteLoaderInitContextImpl(ctmLoadingResultFuture.thenApply(CTMPropertiesLoader.LoadingResult::textureDependencies), wrapEmissiveModels)); + } + + public void clearContext() { + SpriteLoaderLoadContext.THREAD_LOCAL.set(null); + } + + public void beforeBaking(Map preparations, ModelLoader modelLoader) { + CTMPropertiesLoader.LoadingResult result = ctmLoadingResultFuture.join(); + + List processorHolders = CTMPropertiesLoader.createProcessorHolders(result.containers(), spriteId -> { + SpriteAtlasManager.AtlasPreparation preparation = preparations.get(spriteId.getAtlasId()); + Sprite sprite = preparation.getSprite(spriteId.getTextureId()); + if (sprite != null) { + return sprite; + } + return preparation.getMissingSprite(); + }); + + this.processorHolders = processorHolders; + + ((ModelLoaderExtension) modelLoader).continuity$setWrapCTM(!processorHolders.isEmpty()); + ((ModelLoaderExtension) modelLoader).continuity$setWrapEmissive(wrapEmissiveModels.get()); + } + + public void apply() { + List processorHolders = this.processorHolders; + if (processorHolders != null) { + QuadProcessors.reload(processorHolders); + } + } + + private static class SpriteLoaderInitContextImpl implements SpriteLoaderLoadContext { + private final CompletableFuture>> allExtraIdsFuture; + private final Map>> extraIdsFutures = new Object2ObjectOpenHashMap<>(); + private final EmissiveControl blockAtlasEmissiveControl; + private final AtomicReference> emissiveIdMapHolder = new AtomicReference<>(); + + public SpriteLoaderInitContextImpl(CompletableFuture>> allExtraIdsFuture, AtomicBoolean blockAtlasHasEmissivesHolder) { + this.allExtraIdsFuture = allExtraIdsFuture; + blockAtlasEmissiveControl = () -> blockAtlasHasEmissivesHolder.set(true); + } + + @Override + public CompletableFuture<@Nullable Set> getExtraIdsFuture(Identifier atlasId) { + return extraIdsFutures.computeIfAbsent(atlasId, id -> allExtraIdsFuture.thenApply(allExtraIds -> allExtraIds.get(id))); + } + + @Override + @Nullable + public EmissiveControl getEmissiveControl(Identifier atlasId) { + if (atlasId.equals(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE)) { + return blockAtlasEmissiveControl; + } + return null; + } + + @Override + public AtomicReference<@Nullable Map> getEmissiveIdMapHolder() { + return emissiveIdMapHolder; + } + } +} diff --git a/src/main/java/me/pepperbell/continuity/client/resource/CTMLoadingContainer.java b/src/main/java/me/pepperbell/continuity/client/resource/CTMLoadingContainer.java deleted file mode 100644 index 28789a18..00000000 --- a/src/main/java/me/pepperbell/continuity/client/resource/CTMLoadingContainer.java +++ /dev/null @@ -1,80 +0,0 @@ -package me.pepperbell.continuity.client.resource; - -import java.util.Set; -import java.util.function.Function; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import me.pepperbell.continuity.api.client.CTMLoader; -import me.pepperbell.continuity.api.client.CTMProperties; -import me.pepperbell.continuity.api.client.QuadProcessor; -import net.minecraft.client.texture.Sprite; -import net.minecraft.client.util.SpriteIdentifier; - -public class CTMLoadingContainer implements Comparable> { - private final CTMLoader loader; - private final T properties; - - private Set> multipassDependents; - private Set> recursiveMultipassDependents; - - private QuadProcessor cachedProcessor; - - public CTMLoadingContainer(CTMLoader loader, T properties) { - this.loader = loader; - this.properties = properties; - } - - public CTMLoader getLoader() { - return loader; - } - - public T getProperties() { - return properties; - } - - public void addMultipassDependent(CTMLoadingContainer dependent) { - if (multipassDependents == null) { - multipassDependents = new ObjectOpenHashSet<>(); - } - multipassDependents.add(dependent); - } - - public void resolveRecursiveMultipassDependents() { - if (multipassDependents != null) { - recursiveMultipassDependents = new ObjectOpenHashSet<>(); - addDependentsRecursively(this); - } - } - - protected void addDependentsRecursively(CTMLoadingContainer root) { - if (multipassDependents != null) { - for (CTMLoadingContainer dependent : multipassDependents) { - if (dependent != root) { - if (root.recursiveMultipassDependents.add(dependent)) { - dependent.addDependentsRecursively(root); - } - } - } - } - } - - @Nullable - public Set> getRecursiveMultipassDependents() { - return recursiveMultipassDependents; - } - - public QuadProcessor toProcessor(Function textureGetter) { - if (cachedProcessor == null) { - cachedProcessor = loader.getProcessorFactory().createProcessor(properties, textureGetter); - } - return cachedProcessor; - } - - @Override - public int compareTo(@NotNull CTMLoadingContainer o) { - return properties.compareTo(o.properties); - } -} diff --git a/src/main/java/me/pepperbell/continuity/client/resource/CTMPropertiesLoader.java b/src/main/java/me/pepperbell/continuity/client/resource/CTMPropertiesLoader.java index 79097a9c..83540234 100644 --- a/src/main/java/me/pepperbell/continuity/client/resource/CTMPropertiesLoader.java +++ b/src/main/java/me/pepperbell/continuity/client/resource/CTMPropertiesLoader.java @@ -1,25 +1,29 @@ package me.pepperbell.continuity.client.resource; import java.io.InputStream; -import java.util.Collection; +import java.util.Comparator; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Properties; -import java.util.function.Consumer; +import java.util.Set; +import java.util.function.Function; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; -import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import it.unimi.dsi.fastutil.objects.ObjectIterator; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import me.pepperbell.continuity.api.client.CTMLoader; import me.pepperbell.continuity.api.client.CTMLoaderRegistry; import me.pepperbell.continuity.api.client.CTMProperties; +import me.pepperbell.continuity.api.client.CachingPredicates; +import me.pepperbell.continuity.api.client.QuadProcessor; import me.pepperbell.continuity.client.ContinuityClient; +import me.pepperbell.continuity.client.model.QuadProcessors; import me.pepperbell.continuity.client.util.BooleanState; -import net.minecraft.block.BlockState; +import me.pepperbell.continuity.client.util.biome.BiomeHolderManager; +import net.minecraft.client.texture.Sprite; import net.minecraft.client.util.SpriteIdentifier; import net.minecraft.resource.ResourceManager; import net.minecraft.resource.ResourcePack; @@ -27,203 +31,97 @@ import net.minecraft.util.Identifier; public final class CTMPropertiesLoader { - private static final List> ALL = new ObjectArrayList<>(); - private static final List> AFFECTS_BLOCK = new ObjectArrayList<>(); - private static final List> IGNORES_BLOCK = new ObjectArrayList<>(); - private static final List> VALID_FOR_MULTIPASS = new ObjectArrayList<>(); + public static LoadingResult loadAllWithState(ResourceManager resourceManager) { + // TODO: move these to the very beginning of resource reload + BiomeHolderManager.clearCache(); - private static final OptionalListCreator> LIST_CREATOR = new OptionalListCreator<>(); + LoadingResult result = loadAll(resourceManager); + + // TODO: move these to the very end of resource reload + BiomeHolderManager.refreshHolders(); + + return result; + } + + public static LoadingResult loadAll(ResourceManager resourceManager) { + List> containers = new ObjectArrayList<>(); + Map> textureDependencies = new Object2ObjectOpenHashMap<>(); + LoadingResult result = new LoadingResult(containers, textureDependencies); - @ApiStatus.Internal - public static void loadAll(ResourceManager resourceManager) { int packPriority = 0; Iterator iterator = resourceManager.streamResourcePacks().iterator(); BooleanState invalidIdentifierState = InvalidIdentifierStateHolder.get(); invalidIdentifierState.enable(); while (iterator.hasNext()) { ResourcePack pack = iterator.next(); - loadAll(pack, packPriority); + loadAll(pack, packPriority, resourceManager, result); packPriority++; } invalidIdentifierState.disable(); - resolveMultipassDependents(); + containers.sort(Comparator.reverseOrder()); + + return result; } - private static void loadAll(ResourcePack pack, int packPriority) { - String packName = pack.getName(); + private static void loadAll(ResourcePack pack, int packPriority, ResourceManager resourceManager, LoadingResult result) { for (String namespace : pack.getNamespaces(ResourceType.CLIENT_RESOURCES)) { - Collection ids = pack.findResources(ResourceType.CLIENT_RESOURCES, namespace, "optifine/ctm", id -> id.getPath().endsWith(".properties")); - for (Identifier id : ids) { - try (InputStream stream = pack.open(ResourceType.CLIENT_RESOURCES, id)) { - Properties properties = new Properties(); - properties.load(stream); - load(properties, id, packName, packPriority); - } catch (Exception e) { - ContinuityClient.LOGGER.error("Failed to load CTM properties from file '" + id + "' in pack '" + packName + "'", e); + pack.findResources(ResourceType.CLIENT_RESOURCES, namespace, "optifine/ctm", (id, inputSupplier) -> { + if (id.getPath().endsWith(".properties")) { + try (InputStream stream = inputSupplier.get()) { + Properties properties = new Properties(); + properties.load(stream); + load(properties, id, pack, packPriority, resourceManager, result); + } catch (Exception e) { + ContinuityClient.LOGGER.error("Failed to load CTM properties from file '" + id + "' in pack '" + pack.getName() + "'", e); + } } - } + }); } } - private static void load(Properties properties, Identifier id, String packName, int packPriority) { + private static void load(Properties properties, Identifier id, ResourcePack pack, int packPriority, ResourceManager resourceManager, LoadingResult result) { String method = properties.getProperty("method", "ctm").trim(); CTMLoader loader = CTMLoaderRegistry.get().getLoader(method); if (loader != null) { - load(loader, properties, id, packName, packPriority, method); + load(loader, properties, id, pack, packPriority, resourceManager, method, result); } else { - ContinuityClient.LOGGER.error("Unknown 'method' value '" + method + "' in file '" + id + "' in pack '" + packName + "'"); + ContinuityClient.LOGGER.error("Unknown 'method' value '" + method + "' in file '" + id + "' in pack '" + pack.getName() + "'"); } } - private static void load(CTMLoader loader, Properties properties, Identifier id, String packName, int packPriority, String method) { - T ctmProperties = loader.getPropertiesFactory().createProperties(properties, id, packName, packPriority, method); + private static void load(CTMLoader loader, Properties properties, Identifier id, ResourcePack pack, int packPriority, ResourceManager resourceManager, String method, LoadingResult result) { + T ctmProperties = loader.getPropertiesFactory().createProperties(properties, id, pack, packPriority, resourceManager, method); if (ctmProperties != null) { - CTMLoadingContainer container = new CTMLoadingContainer<>(loader, ctmProperties); - ALL.add(container); - if (ctmProperties.affectsBlockStates()) { - AFFECTS_BLOCK.add(container); - } else { - IGNORES_BLOCK.add(container); - } - if (ctmProperties.affectsTextures() && ctmProperties.isValidForMultipass()) { - VALID_FOR_MULTIPASS.add(container); + LoadingContainer container = new LoadingContainer<>(loader, ctmProperties); + result.containers().add(container); + for (SpriteIdentifier spriteId : ctmProperties.getTextureDependencies()) { + Set atlasTextureDependencies = result.textureDependencies().computeIfAbsent(spriteId.getAtlasId(), id1 -> new ObjectOpenHashSet<>()); + atlasTextureDependencies.add(spriteId.getTextureId()); } } } - private static void resolveMultipassDependents() { - if (isEmpty()) { - return; - } - - Object2ObjectOpenHashMap> texture2ContainerMap = new Object2ObjectOpenHashMap<>(); - Object2ObjectOpenHashMap>> texture2ContainerListMap = new Object2ObjectOpenHashMap<>(); - - int amount = ALL.size(); - for (int i = 0; i < amount; i++) { - CTMLoadingContainer container = ALL.get(i); - Collection textureDependencies = container.getProperties().getTextureDependencies(); - for (SpriteIdentifier spriteId : textureDependencies) { - Identifier textureId = spriteId.getTextureId(); - CTMLoadingContainer containerValue = texture2ContainerMap.get(textureId); - if (containerValue == null) { - List> containerListValue = texture2ContainerListMap.get(textureId); - if (containerListValue == null) { - texture2ContainerMap.put(textureId, container); - } else { - containerListValue.add(container); - } - } else { - List> containerList = new ObjectArrayList<>(); - containerList.add(containerValue); - containerList.add(container); - texture2ContainerListMap.put(textureId, containerList); - texture2ContainerMap.remove(textureId); - } - } - } - - int amount1 = VALID_FOR_MULTIPASS.size(); - ObjectIterator>> iterator = texture2ContainerMap.object2ObjectEntrySet().fastIterator(); - while (iterator.hasNext()) { - Object2ObjectMap.Entry> entry = iterator.next(); - Identifier textureId = entry.getKey(); - CTMLoadingContainer container1 = entry.getValue(); - - for (int i = 0; i < amount1; i++) { - CTMLoadingContainer container = VALID_FOR_MULTIPASS.get(i); - if (container.getProperties().affectsTexture(textureId)) { - container1.addMultipassDependent(container); - } - } - } - ObjectIterator>>> iterator1 = texture2ContainerListMap.object2ObjectEntrySet().fastIterator(); - while (iterator1.hasNext()) { - Object2ObjectMap.Entry>> entry = iterator1.next(); - Identifier textureId = entry.getKey(); - List> containerList = entry.getValue(); - int amount2 = containerList.size(); - - for (int i = 0; i < amount1; i++) { - CTMLoadingContainer container = VALID_FOR_MULTIPASS.get(i); - if (container.getProperties().affectsTexture(textureId)) { - for (int j = 0; j < amount2; j++) { - CTMLoadingContainer container1 = containerList.get(j); - container1.addMultipassDependent(container); - } - } - } - } - - for (int i = 0; i < amount; i++) { - CTMLoadingContainer container = ALL.get(i); - container.resolveRecursiveMultipassDependents(); + public static List createProcessorHolders(List> containers, Function textureGetter) { + List processorHolders = new ObjectArrayList<>(); + for (LoadingContainer container : containers) { + processorHolders.add(container.toProcessorHolder(textureGetter)); } + return processorHolders; } - public static void consumeAllAffecting(BlockState state, Consumer> consumer) { - int amount = AFFECTS_BLOCK.size(); - for (int i = 0; i < amount; i++) { - CTMLoadingContainer container = AFFECTS_BLOCK.get(i); - if (container.getProperties().affectsBlockState(state)) { - consumer.accept(container); - } + public record LoadingContainer(CTMLoader loader, T properties) implements Comparable> { + public QuadProcessors.ProcessorHolder toProcessorHolder(Function textureGetter) { + QuadProcessor processor = loader.getProcessorFactory().createProcessor(properties, textureGetter); + CachingPredicates predicates = loader.getPredicatesFactory().createPredicates(properties, textureGetter); + return new QuadProcessors.ProcessorHolder(processor, predicates); } - } - - @Nullable - public static List> getAllAffecting(BlockState state) { - consumeAllAffecting(state, LIST_CREATOR); - return LIST_CREATOR.get(); - } - - public static void consumeAllAffecting(Collection spriteIds, Consumer> consumer) { - int amount = IGNORES_BLOCK.size(); - for (int i = 0; i < amount; i++) { - CTMLoadingContainer container = IGNORES_BLOCK.get(i); - for (SpriteIdentifier spriteId : spriteIds) { - if (container.getProperties().affectsTexture(spriteId.getTextureId())) { - consumer.accept(container); - break; - } - } - } - } - - @Nullable - public static List> getAllAffecting(Collection spriteIds) { - consumeAllAffecting(spriteIds, LIST_CREATOR); - return LIST_CREATOR.get(); - } - - public static boolean isEmpty() { - return ALL.isEmpty(); - } - - @ApiStatus.Internal - public static void clearAll() { - ALL.clear(); - AFFECTS_BLOCK.clear(); - IGNORES_BLOCK.clear(); - VALID_FOR_MULTIPASS.clear(); - } - - private static class OptionalListCreator implements Consumer { - private ObjectArrayList list = null; @Override - public void accept(T t) { - if (list == null) { - list = new ObjectArrayList<>(); - } - list.add(t); + public int compareTo(@NotNull LoadingContainer o) { + return properties.compareTo(o.properties); } + } - @Nullable - public ObjectArrayList get() { - ObjectArrayList list = this.list; - this.list = null; - return list; - } + public record LoadingResult(List> containers, Map> textureDependencies) { } } diff --git a/src/main/java/me/pepperbell/continuity/client/resource/EmissiveIdProvider.java b/src/main/java/me/pepperbell/continuity/client/resource/EmissiveIdProvider.java deleted file mode 100644 index ab3d6474..00000000 --- a/src/main/java/me/pepperbell/continuity/client/resource/EmissiveIdProvider.java +++ /dev/null @@ -1,64 +0,0 @@ -package me.pepperbell.continuity.client.resource; - -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; - -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.util.Identifier; - -public final class EmissiveIdProvider { - private static final Provider PROVIDER = createProvider(); - - private static Provider createProvider() { - if (FabricLoader.getInstance().isModLoaded("citresewn-defaults")) { - return EmissiveIdProvider::toEmissiveIdCITR; - } - - return EmissiveIdProvider::toEmissiveIdStandard; - } - - @Nullable - public static Identifier toEmissiveId(Identifier spriteId, String emissiveSuffix) { - return PROVIDER.toEmissiveId(spriteId, emissiveSuffix); - } - - @ApiStatus.Internal - public static void init() { - } - - @Nullable - private static Identifier toEmissiveIdStandard(Identifier spriteId, String emissiveSuffix) { - String path = spriteId.getPath(); - if (!path.endsWith(emissiveSuffix)) { - return new Identifier(spriteId.getNamespace(), path + emissiveSuffix); - } - return null; - } - - /** - * Sprite identifiers never have an extension in vanilla. CIT Resewn adds a png extension to some identifiers and - * changes SpriteAtlasTexture#getTexturePath to interpret those identifiers as absolute texture locations. This code - * accounts for the possibility of the identifier having a png extension and appends the emissive suffix before it. - */ - @Nullable - private static Identifier toEmissiveIdCITR(Identifier spriteId, String emissiveSuffix) { - String path = spriteId.getPath(); - boolean hasExtension = path.endsWith(".png"); - if (hasExtension) { - path = path.substring(0, path.length() - 4); - } - if (!path.endsWith(emissiveSuffix)) { - String emissivePath = path + emissiveSuffix; - if (hasExtension) { - emissivePath += ".png"; - } - return new Identifier(spriteId.getNamespace(), emissivePath); - } - return null; - } - - private interface Provider { - @Nullable - Identifier toEmissiveId(Identifier spriteId, String emissiveSuffix); - } -} diff --git a/src/main/java/me/pepperbell/continuity/client/resource/ModelWrappingHandler.java b/src/main/java/me/pepperbell/continuity/client/resource/ModelWrappingHandler.java index b2283356..d6c0f22c 100644 --- a/src/main/java/me/pepperbell/continuity/client/resource/ModelWrappingHandler.java +++ b/src/main/java/me/pepperbell/continuity/client/resource/ModelWrappingHandler.java @@ -1,189 +1,48 @@ package me.pepperbell.continuity.client.resource; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Consumer; -import java.util.function.Function; +import com.google.common.collect.ImmutableMap; -import com.mojang.datafixers.util.Pair; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import me.pepperbell.continuity.client.mixinterface.SpriteAtlasTextureDataExtension; -import me.pepperbell.continuity.client.model.CTMUnbakedModel; -import me.pepperbell.continuity.client.model.EmissiveUnbakedModel; -import me.pepperbell.continuity.client.util.VoidSet; +import me.pepperbell.continuity.client.model.CTMBakedModel; +import me.pepperbell.continuity.client.model.EmissiveBakedModel; +import net.minecraft.block.Block; import net.minecraft.block.BlockState; -import net.minecraft.client.render.model.UnbakedModel; -import net.minecraft.client.texture.SpriteAtlasTexture; +import net.minecraft.client.render.block.BlockModels; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.ModelLoader; import net.minecraft.client.util.ModelIdentifier; -import net.minecraft.client.util.SpriteIdentifier; +import net.minecraft.registry.Registries; import net.minecraft.util.Identifier; public final class ModelWrappingHandler { - private static final Map MODEL_ID_2_STATE_MAP = new Object2ObjectOpenHashMap<>(); - private static final Map>> MODEL_ID_2_CONTAINERS_MAP = new Object2ObjectOpenHashMap<>(); - - public static void onAddBlockStateModel(ModelIdentifier id, BlockState state) { - MODEL_ID_2_STATE_MAP.put(id, state); - List> containerList = CTMPropertiesLoader.getAllAffecting(state); - if (containerList != null) { - MODEL_ID_2_CONTAINERS_MAP.put(id, containerList); + private static final ImmutableMap BLOCK_STATE_MODEL_IDS = createBlockStateModelIdMap(); + + private static ImmutableMap createBlockStateModelIdMap() { + ImmutableMap.Builder builder = ImmutableMap.builder(); + // Match code of BakedModelManager#bake + for (Block block : Registries.BLOCK) { + Identifier blockId = block.getRegistryEntry().registryKey().getValue(); + for (BlockState state : block.getStateManager().getStates()) { + ModelIdentifier modelId = BlockModels.getModelId(blockId, state); + builder.put(modelId, state); + } } + return builder.build(); } - public static void wrapCTMModels(Map unbakedModels, Map modelsToBake) { - if (CTMPropertiesLoader.isEmpty()) { - clearMaps(); - return; - } - - Map wrappedModels = new Object2ObjectOpenHashMap<>(); - Function unbakedModelGetter = createUnbakedModelGetter(unbakedModels); - VoidSet> voidSet = VoidSet.get(); - CollectionBasedConsumer> reusableConsumer = new CollectionBasedConsumer<>(); - - modelsToBake.forEach((id, model) -> { - // Only wrap final block state models - if (id instanceof ModelIdentifier modelId && isBlockStateModelId(modelId)) { - Collection dependencies; - try { - dependencies = model.getTextureDependencies(unbakedModelGetter, voidSet); - } catch (ModelNotLoadedException e) { - return; - } - - List> containerList = MODEL_ID_2_CONTAINERS_MAP.get(modelId); - if (containerList == null) { - containerList = CTMPropertiesLoader.getAllAffecting(dependencies); - if (containerList == null) { - return; - } - } else { - reusableConsumer.setCollection(containerList); - CTMPropertiesLoader.consumeAllAffecting(dependencies, reusableConsumer); - } - containerList.sort(Collections.reverseOrder()); - - Set> multipassContainerSet = null; - int amount = containerList.size(); - for (int i = 0; i < amount; i++) { - CTMLoadingContainer container = containerList.get(i); - Set> dependents = container.getRecursiveMultipassDependents(); - if (dependents != null) { - if (multipassContainerSet == null) { - multipassContainerSet = new ObjectOpenHashSet<>(); - } - multipassContainerSet.addAll(dependents); + public static BakedModel wrap(BakedModel model, Identifier modelId, boolean wrapCTM, boolean wrapEmissive) { + if (model != null && !model.isBuiltin() && !modelId.equals(ModelLoader.MISSING_ID)) { + if (wrapCTM) { + if (modelId instanceof ModelIdentifier) { + BlockState state = BLOCK_STATE_MODEL_IDS.get(modelId); + if (state != null) { + model = new CTMBakedModel(model, state); } } - List> multipassContainerList = null; - if (multipassContainerSet != null) { - BlockState state = MODEL_ID_2_STATE_MAP.get(modelId); - for (CTMLoadingContainer container : multipassContainerSet) { - if (!container.getProperties().affectsBlockStates() || container.getProperties().affectsBlockState(state)) { - if (multipassContainerList == null) { - multipassContainerList = new ObjectArrayList<>(); - } - multipassContainerList.add(container); - } - } - if (multipassContainerList != null) { - multipassContainerList.sort(Collections.reverseOrder()); - } - } - - wrappedModels.put(modelId, new CTMUnbakedModel(model, containerList, multipassContainerList)); } - }); - - clearMaps(); - injectWrappedModels(wrappedModels, unbakedModels, modelsToBake); - } - - public static void wrapEmissiveModels(Map> spriteAtlasData, Map unbakedModels, Map modelsToBake) { - Set spriteIdsToWrap = new ObjectOpenHashSet<>(); - - spriteAtlasData.forEach((atlasId, pair) -> { - SpriteAtlasTexture.Data data = pair.getSecond(); - Map emissiveIdMap = ((SpriteAtlasTextureDataExtension) data).continuity$getEmissiveIdMap(); - if (emissiveIdMap != null) { - for (Identifier id : emissiveIdMap.keySet()) { - spriteIdsToWrap.add(new SpriteIdentifier(atlasId, id)); - } + if (wrapEmissive) { + model = new EmissiveBakedModel(model); } - }); - - if (spriteIdsToWrap.isEmpty()) { - return; - } - - Map wrappedModels = new Object2ObjectOpenHashMap<>(); - Function unbakedModelGetter = createUnbakedModelGetter(unbakedModels); - VoidSet> voidSet = VoidSet.get(); - - unbakedModels.forEach((id, model) -> { - Collection dependencies; - try { - dependencies = model.getTextureDependencies(unbakedModelGetter, voidSet); - } catch (ModelNotLoadedException e) { - return; - } - - for (SpriteIdentifier spriteId : dependencies) { - if (spriteIdsToWrap.contains(spriteId)) { - wrappedModels.put(id, new EmissiveUnbakedModel(model)); - return; - } - } - }); - - injectWrappedModels(wrappedModels, unbakedModels, modelsToBake); - } - - private static Function createUnbakedModelGetter(Map unbakedModels) { - return id -> { - UnbakedModel model = unbakedModels.get(id); - if (model == null) { - throw new ModelNotLoadedException(); - } - return model; - }; - } - - private static void injectWrappedModels(Map wrappedModels, Map unbakedModels, Map modelsToBake) { - wrappedModels.forEach((id, wrapped) -> { - unbakedModels.replace(id, wrapped); - modelsToBake.replace(id, wrapped); - }); - } - - private static boolean isBlockStateModelId(ModelIdentifier id) { - return !id.getVariant().equals("inventory"); - } - - private static void clearMaps() { - MODEL_ID_2_STATE_MAP.clear(); - MODEL_ID_2_CONTAINERS_MAP.clear(); - } - - private static class ModelNotLoadedException extends RuntimeException { - } - - private static class CollectionBasedConsumer implements Consumer { - private Collection collection; - - @Override - public void accept(T t) { - collection.add(t); - } - - public void setCollection(Collection collection) { - this.collection = collection; } + return model; } } diff --git a/src/main/java/me/pepperbell/continuity/client/resource/ResourcePackUtil.java b/src/main/java/me/pepperbell/continuity/client/resource/ResourcePackUtil.java deleted file mode 100644 index 9287008f..00000000 --- a/src/main/java/me/pepperbell/continuity/client/resource/ResourcePackUtil.java +++ /dev/null @@ -1,41 +0,0 @@ -package me.pepperbell.continuity.client.resource; - -import org.apache.commons.lang3.ArrayUtils; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.resource.DefaultResourcePack; -import net.minecraft.resource.ResourceManager; -import net.minecraft.resource.ResourcePack; -import net.minecraft.resource.ResourceType; -import net.minecraft.util.Identifier; - -public final class ResourcePackUtil { - private static ResourcePack[] resourcePacks; - - public static DefaultResourcePack getDefaultResourcePack() { - return MinecraftClient.getInstance().getResourcePackProvider().getPack(); - } - - @ApiStatus.Internal - public static void setup(ResourceManager resourceManager) { - resourcePacks = resourceManager.streamResourcePacks().toArray(ResourcePack[]::new); - ArrayUtils.reverse(resourcePacks); - } - - @Nullable - public static ResourcePack getProvidingResourcePack(Identifier resourceId) { - for (ResourcePack resourcePack : resourcePacks) { - if (resourcePack.contains(ResourceType.CLIENT_RESOURCES, resourceId)) { - return resourcePack; - } - } - return null; - } - - @ApiStatus.Internal - public static void clear() { - resourcePacks = null; - } -} diff --git a/src/main/java/me/pepperbell/continuity/client/resource/ResourceRedirectHandler.java b/src/main/java/me/pepperbell/continuity/client/resource/ResourceRedirectHandler.java index ff02aba8..58cef428 100644 --- a/src/main/java/me/pepperbell/continuity/client/resource/ResourceRedirectHandler.java +++ b/src/main/java/me/pepperbell/continuity/client/resource/ResourceRedirectHandler.java @@ -10,7 +10,6 @@ import me.pepperbell.continuity.client.mixin.ReloadableResourceManagerImplAccessor; import me.pepperbell.continuity.client.mixinterface.LifecycledResourceManagerImplExtension; import me.pepperbell.continuity.client.util.BooleanState; -import net.minecraft.client.MinecraftClient; import net.minecraft.resource.ResourceManager; import net.minecraft.util.Identifier; @@ -51,11 +50,6 @@ public static ResourceRedirectHandler get(ResourceManager resourceManager) { return null; } - @Nullable - public static ResourceRedirectHandler get() { - return get(MinecraftClient.getInstance().getResourceManager()); - } - public String getSourceSpritePath(String absolutePath) { int index = indexMap.getInt(absolutePath); if (index == -1) { diff --git a/src/main/java/me/pepperbell/continuity/client/resource/SpriteLoaderLoadContext.java b/src/main/java/me/pepperbell/continuity/client/resource/SpriteLoaderLoadContext.java new file mode 100644 index 00000000..f97b305e --- /dev/null +++ b/src/main/java/me/pepperbell/continuity/client/resource/SpriteLoaderLoadContext.java @@ -0,0 +1,25 @@ +package me.pepperbell.continuity.client.resource; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicReference; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.util.Identifier; + +public interface SpriteLoaderLoadContext { + ThreadLocal THREAD_LOCAL = new ThreadLocal<>(); + + CompletableFuture<@Nullable Set> getExtraIdsFuture(Identifier atlasId); + + @Nullable + EmissiveControl getEmissiveControl(Identifier atlasId); + + AtomicReference<@Nullable Map> getEmissiveIdMapHolder(); + + interface EmissiveControl { + void markHasEmissives(); + } +} diff --git a/src/main/java/me/pepperbell/continuity/client/resource/SpriteLoaderStitchContext.java b/src/main/java/me/pepperbell/continuity/client/resource/SpriteLoaderStitchContext.java new file mode 100644 index 00000000..872993b2 --- /dev/null +++ b/src/main/java/me/pepperbell/continuity/client/resource/SpriteLoaderStitchContext.java @@ -0,0 +1,13 @@ +package me.pepperbell.continuity.client.resource; + +import java.util.Map; + +import net.minecraft.util.Identifier; + +public interface SpriteLoaderStitchContext { + ThreadLocal THREAD_LOCAL = new ThreadLocal<>(); + + Map getEmissiveIdMap(); + + void markHasEmissives(); +} diff --git a/src/main/java/me/pepperbell/continuity/client/util/TextureUtil.java b/src/main/java/me/pepperbell/continuity/client/util/TextureUtil.java index fcfa3640..2c17be64 100644 --- a/src/main/java/me/pepperbell/continuity/client/util/TextureUtil.java +++ b/src/main/java/me/pepperbell/continuity/client/util/TextureUtil.java @@ -14,6 +14,6 @@ public static SpriteIdentifier toSpriteId(Identifier id) { } public static boolean isMissingSprite(Sprite sprite) { - return sprite instanceof MissingSprite; + return sprite.getContents().getId().equals(MissingSprite.getMissingSpriteId()); } } diff --git a/src/main/java/me/pepperbell/continuity/client/util/VoidSet.java b/src/main/java/me/pepperbell/continuity/client/util/VoidSet.java deleted file mode 100644 index a0d205b7..00000000 --- a/src/main/java/me/pepperbell/continuity/client/util/VoidSet.java +++ /dev/null @@ -1,98 +0,0 @@ -package me.pepperbell.continuity.client.util; - -import java.util.Collection; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.Set; - -public class VoidSet implements Set { - public static final VoidSet INSTANCE = new VoidSet<>(); - - @SuppressWarnings("unchecked") - public static VoidSet get() { - return (VoidSet) INSTANCE; - } - - @Override - public int size() { - return 0; - } - - @Override - public boolean isEmpty() { - return true; - } - - @Override - public boolean contains(Object o) { - return false; - } - - @Override - public Iterator iterator() { - return VoidIterator.get(); - } - - @Override - public Object[] toArray() { - return new Object[0]; - } - - @Override - public V[] toArray(V[] a) { - return a; - } - - @Override - public boolean add(T e) { - return true; - } - - @Override - public boolean remove(Object o) { - return false; - } - - @Override - public boolean containsAll(Collection c) { - return c.isEmpty(); - } - - @Override - public boolean addAll(Collection c) { - return false; - } - - @Override - public boolean retainAll(Collection c) { - return false; - } - - @Override - public boolean removeAll(Collection c) { - return false; - } - - @Override - public void clear() { - } - - public static class VoidIterator implements Iterator { - public static final VoidIterator INSTANCE = new VoidIterator<>(); - - @SuppressWarnings("unchecked") - public static VoidIterator get() { - return (VoidIterator) INSTANCE; - } - - @Override - public boolean hasNext() { - return false; - } - - @Override - public T next() { - throw new NoSuchElementException(); - } - } -} diff --git a/src/main/java/me/pepperbell/continuity/client/util/biome/BiomeHolder.java b/src/main/java/me/pepperbell/continuity/client/util/biome/BiomeHolder.java index 1fa7b8ca..583ef5f0 100644 --- a/src/main/java/me/pepperbell/continuity/client/util/biome/BiomeHolder.java +++ b/src/main/java/me/pepperbell/continuity/client/util/biome/BiomeHolder.java @@ -5,8 +5,8 @@ import org.jetbrains.annotations.Nullable; import me.pepperbell.continuity.client.ContinuityClient; +import net.minecraft.registry.Registry; import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; import net.minecraft.world.biome.Biome; public class BiomeHolder { diff --git a/src/main/java/me/pepperbell/continuity/client/util/biome/BiomeHolderManager.java b/src/main/java/me/pepperbell/continuity/client/util/biome/BiomeHolderManager.java index 1de03caa..3033792a 100644 --- a/src/main/java/me/pepperbell/continuity/client/util/biome/BiomeHolderManager.java +++ b/src/main/java/me/pepperbell/continuity/client/util/biome/BiomeHolderManager.java @@ -6,9 +6,10 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; +import net.minecraft.registry.DynamicRegistryManager; +import net.minecraft.registry.Registry; +import net.minecraft.registry.RegistryKeys; import net.minecraft.util.Identifier; -import net.minecraft.util.registry.DynamicRegistryManager; -import net.minecraft.util.registry.Registry; import net.minecraft.world.biome.Biome; public final class BiomeHolderManager { @@ -38,7 +39,7 @@ public static void refreshHolders() { } Map compressedIdMap = new Object2ObjectOpenHashMap<>(); - Registry biomeRegistry = registryManager.get(Registry.BIOME_KEY); + Registry biomeRegistry = registryManager.get(RegistryKeys.BIOME); for (Identifier id : biomeRegistry.getIds()) { String path = id.getPath(); String compressedPath = path.replace("_", ""); diff --git a/src/main/resources/assets/continuity/lang/en_us.json b/src/main/resources/assets/continuity/lang/en_us.json index c9b4cef7..c23a9257 100644 --- a/src/main/resources/assets/continuity/lang/en_us.json +++ b/src/main/resources/assets/continuity/lang/en_us.json @@ -5,5 +5,9 @@ "options.continuity.emissive_textures": "Emissive Textures", "options.continuity.emissive_textures.tooltip": "Enable or disable emissive textures for block and item models.", "options.continuity.custom_block_layers": "Custom Block Layers", - "options.continuity.custom_block_layers.tooltip": "Enable or disable custom block layers." + "options.continuity.custom_block_layers.tooltip": "Enable or disable custom block layers.", + "resourcePack.continuity.default.name": "Default Connected Textures", + "resourcePack.continuity.default.description": "Bookshelves, sandstone, and glass", + "resourcePack.continuity.glass_pane_culling_fix.name": "Glass Pane Culling Fix", + "resourcePack.continuity.glass_pane_culling_fix.description": "Fixes top and bottom face culling" } diff --git a/src/main/resources/continuity.mixins.json b/src/main/resources/continuity.mixins.json index 6a451e92..246fa45a 100644 --- a/src/main/resources/continuity.mixins.json +++ b/src/main/resources/continuity.mixins.json @@ -4,19 +4,20 @@ "package": "me.pepperbell.continuity.client.mixin", "compatibilityLevel": "JAVA_17", "client": [ + "AtlasLoaderMixin", + "BakedModelManagerMixin", "BlockModelsMixin", "ChunkRendererRegionMixin", "FallingBlockEntityRendererMixin", "IdentifierMixin", "LifecycledResourceManagerImplMixin", - "ModelLoaderAccessor", + "ModelLoaderBakerImplMixin", "ModelLoaderMixin", "NamespaceResourceManagerMixin", "PistonBlockEntityRendererMixin", "ReloadableResourceManagerImplAccessor", "RenderLayersMixin", - "SpriteAtlasTextureDataMixin", - "SpriteAtlasTextureMixin", + "SpriteLoaderMixin", "SpriteMixin" ], "injectors": { diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index d4ac6648..62538feb 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -33,7 +33,7 @@ "depends": { "fabricloader": ">=0.11.7", "fabric": ">=0.58.0", - "minecraft": "1.19.x", + "minecraft": ">=1.19.3", "java": ">=17" }, diff --git a/src/main/resources/resourcepacks/default/pack.mcmeta b/src/main/resources/resourcepacks/default/pack.mcmeta index 161b11f6..529eb8f1 100644 --- a/src/main/resources/resourcepacks/default/pack.mcmeta +++ b/src/main/resources/resourcepacks/default/pack.mcmeta @@ -1,6 +1,8 @@ { "pack": { - "pack_format": 9, - "description": "Default connected textures for Continuity" + "pack_format": 12, + "description": { + "translate": "resourcePack.continuity.default.description" + } } } diff --git a/src/main/resources/resourcepacks/glass_pane_culling_fix/pack.mcmeta b/src/main/resources/resourcepacks/glass_pane_culling_fix/pack.mcmeta index 435bfa14..a0596759 100644 --- a/src/main/resources/resourcepacks/glass_pane_culling_fix/pack.mcmeta +++ b/src/main/resources/resourcepacks/glass_pane_culling_fix/pack.mcmeta @@ -1,6 +1,8 @@ { "pack": { - "pack_format": 9, - "description": "Glass pane culling fix" + "pack_format": 12, + "description": { + "translate": "resourcePack.continuity.glass_pane_culling_fix.description" + } } }