package com.tiedup.remake.client.gltf; import com.mojang.blaze3d.platform.InputConstants; import com.tiedup.remake.client.animation.context.ContextAnimationFactory; import com.tiedup.remake.client.animation.context.ContextGlbRegistry; import com.tiedup.remake.v2.bondage.client.V2BondageRenderLayer; import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemReloadListener; import net.minecraft.client.KeyMapping; import net.minecraft.client.renderer.entity.player.PlayerRenderer; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.SimplePreparableReloadListener; import net.minecraft.util.profiling.ProfilerFiller; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.EntityRenderersEvent; import net.minecraftforge.client.event.RegisterClientReloadListenersEvent; import net.minecraftforge.client.event.RegisterKeyMappingsEvent; import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** * Forge event registration for the glTF pipeline. * Registers keybind (F9), render layers, and animation factory. */ public final class GltfClientSetup { private static final Logger LOGGER = LogManager.getLogger("GltfPipeline"); private static final String KEY_CATEGORY = "key.categories.tiedup"; static final KeyMapping TOGGLE_KEY = new KeyMapping( "key.tiedup.gltf_toggle", InputConstants.Type.KEYSYM, InputConstants.KEY_F9, KEY_CATEGORY ); private GltfClientSetup() {} /** * MOD bus event subscribers (FMLClientSetupEvent, RegisterKeyMappings, AddLayers). */ @Mod.EventBusSubscriber( modid = "tiedup", bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT ) public static class ModBusEvents { @SubscribeEvent public static void onClientSetup(FMLClientSetupEvent event) { event.enqueueWork(() -> { GltfCache.init(); GltfAnimationApplier.init(); LOGGER.info("[GltfPipeline] Client setup complete"); }); } @SubscribeEvent public static void onRegisterKeybindings( RegisterKeyMappingsEvent event ) { event.register(TOGGLE_KEY); LOGGER.info("[GltfPipeline] Keybind registered: F9"); } @SuppressWarnings("unchecked") @SubscribeEvent public static void onAddLayers(EntityRenderersEvent.AddLayers event) { // Add GltfRenderLayer (prototype/debug with F9 toggle) to player renderers var defaultRenderer = event.getSkin("default"); if (defaultRenderer instanceof PlayerRenderer playerRenderer) { playerRenderer.addLayer(new GltfRenderLayer(playerRenderer)); playerRenderer.addLayer( new V2BondageRenderLayer<>(playerRenderer) ); LOGGER.info( "[GltfPipeline] Render layers added to 'default' player renderer" ); } // Add both layers to slim player renderer (Alex) var slimRenderer = event.getSkin("slim"); if (slimRenderer instanceof PlayerRenderer playerRenderer) { playerRenderer.addLayer(new GltfRenderLayer(playerRenderer)); playerRenderer.addLayer( new V2BondageRenderLayer<>(playerRenderer) ); LOGGER.info( "[GltfPipeline] Render layers added to 'slim' player renderer" ); } } /** * Register resource reload listener to clear GLB caches on resource pack reload. * This ensures re-exported GLB models are picked up without restarting the game. */ @SubscribeEvent public static void onRegisterReloadListeners( RegisterClientReloadListenersEvent event ) { event.registerReloadListener( new SimplePreparableReloadListener() { @Override protected Void prepare( ResourceManager resourceManager, ProfilerFiller profiler ) { return null; } @Override protected void apply( Void nothing, ResourceManager resourceManager, ProfilerFiller profiler ) { GltfCache.clearCache(); GltfAnimationApplier.invalidateCache(); GltfMeshRenderer.clearRenderTypeCache(); // Reload context GLB animations from resource packs FIRST, // then clear the factory cache so it rebuilds against the // new GLB registry (prevents stale JSON fallback caching). ContextGlbRegistry.reload(resourceManager); ContextAnimationFactory.clearCache(); com.tiedup.remake.v2.furniture.client.FurnitureGltfCache.clear(); LOGGER.info( "[GltfPipeline] Caches cleared on resource reload" ); } } ); LOGGER.info("[GltfPipeline] Resource reload listener registered"); // Data-driven bondage item definitions (tiedup_items/*.json) event.registerReloadListener(new DataDrivenItemReloadListener()); LOGGER.info( "[GltfPipeline] Data-driven item reload listener registered" ); } } /** * FORGE bus event subscribers (ClientTickEvent for keybind toggle). */ @Mod.EventBusSubscriber( modid = "tiedup", bus = Mod.EventBusSubscriber.Bus.FORGE, value = Dist.CLIENT ) public static class ForgeBusEvents { @SubscribeEvent public static void onClientTick(TickEvent.ClientTickEvent event) { if (event.phase != TickEvent.Phase.END) return; while (TOGGLE_KEY.consumeClick()) { GltfAnimationApplier.toggle(); } } } }