From a935859b24916d45287b692f87765a14c3cd29d9 Mon Sep 17 00:00:00 2001 From: gegy1000 Date: Sun, 29 Jul 2018 02:47:01 +0200 Subject: [PATCH] Resource type sensitive ResourceManager reloading, Disabled by default, but may increase performance. (#4658) --- .../net/minecraft/client/Minecraft.java.patch | 74 +++++++++++------- .../client/gui/GuiLanguage.java.patch | 11 +++ .../gui/recipebook/GuiRecipeBook.java.patch | 9 +++ .../IResourceManagerReloadListener.java.patch | 14 ++++ ...SimpleReloadableResourceManager.java.patch | 3 +- .../client/settings/GameSettings.java.patch | 19 +++-- .../minecraftforge/client/CloudRenderer.java | 15 +++- .../client/ForgeHooksClient.java | 35 +++++++++ .../client/model/ICustomModelLoader.java | 21 ++++- .../client/resource/IResourceType.java | 31 ++++++++ .../ISelectiveResourceReloadListener.java | 46 +++++++++++ .../client/resource/ReloadRequirements.java | 57 ++++++++++++++ .../resource/SelectiveReloadStateHandler.java | 76 +++++++++++++++++++ .../client/resource/VanillaResourceType.java | 58 ++++++++++++++ .../client/resource/package-info.java | 26 +++++++ .../common/ForgeModContainer.java | 7 ++ .../fml/client/FMLClientHandler.java | 29 +++++++ .../resources/assets/forge/lang/en_US.lang | 2 + 18 files changed, 493 insertions(+), 40 deletions(-) create mode 100644 patches/minecraft/net/minecraft/client/gui/GuiLanguage.java.patch create mode 100644 patches/minecraft/net/minecraft/client/resources/IResourceManagerReloadListener.java.patch create mode 100644 src/main/java/net/minecraftforge/client/resource/IResourceType.java create mode 100644 src/main/java/net/minecraftforge/client/resource/ISelectiveResourceReloadListener.java create mode 100644 src/main/java/net/minecraftforge/client/resource/ReloadRequirements.java create mode 100644 src/main/java/net/minecraftforge/client/resource/SelectiveReloadStateHandler.java create mode 100644 src/main/java/net/minecraftforge/client/resource/VanillaResourceType.java create mode 100644 src/main/java/net/minecraftforge/client/resource/package-info.java diff --git a/patches/minecraft/net/minecraft/client/Minecraft.java.patch b/patches/minecraft/net/minecraft/client/Minecraft.java.patch index a8a4ff4ac..86476fd5e 100644 --- a/patches/minecraft/net/minecraft/client/Minecraft.java.patch +++ b/patches/minecraft/net/minecraft/client/Minecraft.java.patch @@ -113,7 +113,15 @@ } public boolean func_152349_b() -@@ -955,11 +967,6 @@ +@@ -770,6 +782,7 @@ + return this.field_135017_as.func_135042_a() || this.field_71474_y.field_151455_aw; + } + ++ @Deprecated // Forge: Use selective refreshResources method in FMLClientHandler + public void func_110436_a() + { + List list = Lists.newArrayList(this.field_110449_ao); +@@ -955,11 +968,6 @@ public void func_147108_a(@Nullable GuiScreen p_147108_1_) { @@ -125,7 +133,7 @@ if (p_147108_1_ == null && this.field_71441_e == null) { p_147108_1_ = new GuiMainMenu(); -@@ -969,6 +976,17 @@ +@@ -969,6 +977,17 @@ p_147108_1_ = new GuiGameOver((ITextComponent)null); } @@ -143,7 +151,7 @@ if (p_147108_1_ instanceof GuiMainMenu || p_147108_1_ instanceof GuiMultiplayer) { this.field_71474_y.field_74330_P = false; -@@ -1082,7 +1100,7 @@ +@@ -1082,7 +1101,7 @@ long i1 = System.nanoTime() - l; this.func_71361_d("Pre render"); this.field_71424_I.func_76318_c("sound"); @@ -152,7 +160,7 @@ this.field_71424_I.func_76319_b(); this.field_71424_I.func_76320_a("render"); GlStateManager.func_179094_E(); -@@ -1094,11 +1112,13 @@ +@@ -1094,11 +1113,13 @@ if (!this.field_71454_w) { @@ -166,7 +174,7 @@ } this.field_71424_I.func_76319_b(); -@@ -1455,9 +1475,9 @@ +@@ -1455,9 +1476,9 @@ { BlockPos blockpos = this.field_71476_x.func_178782_a(); @@ -178,7 +186,7 @@ this.field_71439_g.func_184609_a(EnumHand.MAIN_HAND); } } -@@ -1491,7 +1511,7 @@ +@@ -1491,7 +1512,7 @@ case BLOCK: BlockPos blockpos = this.field_71476_x.func_178782_a(); @@ -187,7 +195,7 @@ { this.field_71442_b.func_180511_b(blockpos, this.field_71476_x.field_178784_b); break; -@@ -1505,6 +1525,7 @@ +@@ -1505,6 +1526,7 @@ } this.field_71439_g.func_184821_cY(); @@ -195,7 +203,7 @@ } this.field_71439_g.func_184609_a(EnumHand.MAIN_HAND); -@@ -1570,6 +1591,7 @@ +@@ -1570,6 +1592,7 @@ } } @@ -203,7 +211,7 @@ if (!itemstack.func_190926_b() && this.field_71442_b.func_187101_a(this.field_71439_g, this.field_71441_e, enumhand) == EnumActionResult.SUCCESS) { this.field_71460_t.field_78516_c.func_187460_a(enumhand); -@@ -1630,6 +1652,11 @@ +@@ -1630,6 +1653,11 @@ } Display.setFullscreen(this.field_71431_Q); @@ -215,7 +223,7 @@ Display.setVSyncEnabled(this.field_71474_y.field_74352_v); this.func_175601_h(); } -@@ -1676,6 +1703,8 @@ +@@ -1676,6 +1704,8 @@ --this.field_71467_ac; } @@ -224,7 +232,7 @@ this.field_71424_I.func_76320_a("gui"); if (!this.field_71445_n) -@@ -1877,6 +1906,7 @@ +@@ -1877,6 +1907,7 @@ } this.field_71424_I.func_76319_b(); @@ -232,7 +240,7 @@ this.field_71423_H = func_71386_F(); } -@@ -1982,6 +2012,7 @@ +@@ -1982,6 +2013,7 @@ } } } @@ -240,7 +248,7 @@ } this.func_184117_aA(); -@@ -2239,6 +2270,8 @@ +@@ -2239,6 +2271,8 @@ { while (Mouse.next()) { @@ -249,7 +257,7 @@ int i = Mouse.getEventButton(); KeyBinding.func_74510_a(i - 100, Mouse.getEventButtonState()); -@@ -2294,6 +2327,7 @@ +@@ -2294,6 +2328,7 @@ this.field_71462_r.func_146274_d(); } } @@ -257,7 +265,7 @@ } } -@@ -2304,6 +2338,7 @@ +@@ -2304,6 +2339,7 @@ public void func_71371_a(String p_71371_1_, String p_71371_2_, @Nullable WorldSettings p_71371_3_) { @@ -265,7 +273,7 @@ this.func_71403_a((WorldClient)null); System.gc(); ISaveHandler isavehandler = this.field_71469_aa.func_75804_a(p_71371_1_, false); -@@ -2344,8 +2379,14 @@ +@@ -2344,8 +2380,14 @@ this.field_71461_s.func_73720_a(I18n.func_135052_a("menu.loadingLevel")); @@ -281,7 +289,7 @@ String s = this.field_71437_Z.func_71195_b_(); if (s != null) -@@ -2371,8 +2412,14 @@ +@@ -2371,8 +2413,14 @@ SocketAddress socketaddress = this.field_71437_Z.func_147137_ag().func_151270_a(); NetworkManager networkmanager = NetworkManager.func_150722_a(socketaddress); networkmanager.func_150719_a(new NetHandlerLoginClient(networkmanager, this, (GuiScreen)null)); @@ -298,7 +306,7 @@ this.field_71453_ak = networkmanager; } -@@ -2383,6 +2430,8 @@ +@@ -2383,6 +2431,8 @@ public void func_71353_a(@Nullable WorldClient p_71353_1_, String p_71353_2_) { @@ -307,7 +315,7 @@ if (p_71353_1_ == null) { NetHandlerPlayClient nethandlerplayclient = this.func_147114_u(); -@@ -2395,6 +2444,18 @@ +@@ -2395,6 +2445,18 @@ if (this.field_71437_Z != null && this.field_71437_Z.func_175578_N()) { this.field_71437_Z.func_71263_m(); @@ -326,7 +334,7 @@ } this.field_71437_Z = null; -@@ -2418,6 +2479,7 @@ +@@ -2418,6 +2480,7 @@ this.field_71456_v.func_181029_i(); this.func_71351_a((ServerData)null); this.field_71455_al = false; @@ -334,7 +342,7 @@ } this.field_147127_av.func_147690_c(); -@@ -2434,6 +2496,7 @@ +@@ -2434,6 +2497,7 @@ } TileEntityRendererDispatcher.field_147556_a.func_147543_a(p_71353_1_); @@ -342,7 +350,7 @@ if (p_71353_1_ != null) { -@@ -2488,6 +2551,7 @@ +@@ -2488,6 +2552,7 @@ EntityPlayerSP entityplayersp = this.field_71439_g; this.field_71439_g = this.field_71442_b.func_192830_a(this.field_71441_e, this.field_71439_g == null ? new StatisticsManager() : this.field_71439_g.func_146107_m(), this.field_71439_g == null ? new RecipeBook() : this.field_71439_g.func_192035_E()); this.field_71439_g.func_184212_Q().func_187218_a(entityplayersp.func_184212_Q().func_187231_c()); @@ -350,7 +358,7 @@ this.field_71439_g.field_71093_bK = p_71354_1_; this.field_175622_Z = this.field_71439_g; this.field_71439_g.func_70065_x(); -@@ -2535,159 +2599,8 @@ +@@ -2535,159 +2600,8 @@ { if (this.field_71476_x != null && this.field_71476_x.field_72313_a != RayTraceResult.Type.MISS) { @@ -512,7 +520,15 @@ } } -@@ -3009,18 +2922,8 @@ +@@ -2834,6 +2748,7 @@ + return field_71432_P; + } + ++ @Deprecated // Forge: Use selective scheduleResourceRefresh method in FMLClientHandler + public ListenableFuture func_175603_A() + { + return this.func_152344_a(new Runnable() +@@ -3009,18 +2924,8 @@ public static int func_71369_N() { @@ -533,7 +549,7 @@ } public boolean func_70002_Q() -@@ -3152,6 +3055,9 @@ +@@ -3152,6 +3057,9 @@ } else if (this.field_71439_g != null) { @@ -543,7 +559,7 @@ if (this.field_71439_g.field_70170_p.field_73011_w instanceof WorldProviderHell) { return MusicTicker.MusicType.NETHER; -@@ -3181,11 +3087,11 @@ +@@ -3181,11 +3089,11 @@ { if (Keyboard.getEventKeyState()) { @@ -557,7 +573,7 @@ { this.field_71456_v.func_146158_b().func_146227_a(ScreenShotHelper.func_148260_a(this.field_71412_D, this.field_71443_c, this.field_71440_d, this.field_147124_at)); } -@@ -3199,6 +3105,7 @@ +@@ -3199,6 +3107,7 @@ } } } @@ -565,7 +581,7 @@ } } } -@@ -3328,6 +3235,12 @@ +@@ -3328,6 +3237,12 @@ return this.field_184127_aH; } @@ -578,7 +594,7 @@ public boolean func_189648_am() { return this.field_71439_g != null && this.field_71439_g.func_175140_cp() || this.field_71474_y.field_178879_v; -@@ -3342,4 +3255,9 @@ +@@ -3342,4 +3257,9 @@ { return this.field_193035_aW; } diff --git a/patches/minecraft/net/minecraft/client/gui/GuiLanguage.java.patch b/patches/minecraft/net/minecraft/client/gui/GuiLanguage.java.patch new file mode 100644 index 000000000..550d424ef --- /dev/null +++ b/patches/minecraft/net/minecraft/client/gui/GuiLanguage.java.patch @@ -0,0 +1,11 @@ +--- ../src-base/minecraft/net/minecraft/client/gui/GuiLanguage.java ++++ ../src-work/minecraft/net/minecraft/client/gui/GuiLanguage.java +@@ -108,7 +108,7 @@ + Language language = this.field_148177_m.get(this.field_148176_l.get(p_148144_1_)); + GuiLanguage.this.field_146454_h.func_135045_a(language); + GuiLanguage.this.field_146451_g.field_74363_ab = language.func_135034_a(); +- this.field_148161_k.func_110436_a(); ++ net.minecraftforge.fml.client.FMLClientHandler.instance().refreshResources(net.minecraftforge.client.resource.VanillaResourceType.LANGUAGES); + GuiLanguage.this.field_146289_q.func_78264_a(GuiLanguage.this.field_146454_h.func_135042_a() || GuiLanguage.this.field_146451_g.field_151455_aw); + GuiLanguage.this.field_146289_q.func_78275_b(GuiLanguage.this.field_146454_h.func_135044_b()); + GuiLanguage.this.field_146452_r.field_146126_j = I18n.func_135052_a("gui.done"); diff --git a/patches/minecraft/net/minecraft/client/gui/recipebook/GuiRecipeBook.java.patch b/patches/minecraft/net/minecraft/client/gui/recipebook/GuiRecipeBook.java.patch index b7c6c0ee2..1954aadbe 100644 --- a/patches/minecraft/net/minecraft/client/gui/recipebook/GuiRecipeBook.java.patch +++ b/patches/minecraft/net/minecraft/client/gui/recipebook/GuiRecipeBook.java.patch @@ -1,5 +1,14 @@ --- ../src-base/minecraft/net/minecraft/client/gui/recipebook/GuiRecipeBook.java +++ ../src-work/minecraft/net/minecraft/client/gui/recipebook/GuiRecipeBook.java +@@ -448,7 +448,7 @@ + + languagemanager.func_135045_a(language); + this.field_191888_F.field_71474_y.field_74363_ab = language.func_135034_a(); +- this.field_191888_F.func_110436_a(); ++ net.minecraftforge.fml.client.FMLClientHandler.instance().refreshResources(net.minecraftforge.client.resource.VanillaResourceType.LANGUAGES); + this.field_191888_F.field_71466_p.func_78264_a(this.field_191888_F.func_135016_M().func_135042_a() || this.field_191888_F.field_71474_y.field_151455_aw); + this.field_191888_F.field_71466_p.func_78275_b(languagemanager.func_135044_b()); + this.field_191888_F.field_71474_y.func_74303_b(); @@ -485,7 +485,7 @@ this.field_191915_z.func_194187_a(Ingredient.func_193369_a(itemstack), (p_193951_2_.get(0)).field_75223_e, (p_193951_2_.get(0)).field_75221_f); int i = this.field_193961_o.func_174922_i(); diff --git a/patches/minecraft/net/minecraft/client/resources/IResourceManagerReloadListener.java.patch b/patches/minecraft/net/minecraft/client/resources/IResourceManagerReloadListener.java.patch new file mode 100644 index 000000000..770d1713a --- /dev/null +++ b/patches/minecraft/net/minecraft/client/resources/IResourceManagerReloadListener.java.patch @@ -0,0 +1,14 @@ +--- ../src-base/minecraft/net/minecraft/client/resources/IResourceManagerReloadListener.java ++++ ../src-work/minecraft/net/minecraft/client/resources/IResourceManagerReloadListener.java +@@ -3,6 +3,11 @@ + import net.minecraftforge.fml.relauncher.Side; + import net.minecraftforge.fml.relauncher.SideOnly; + ++/** ++ * @deprecated Forge: {@link net.minecraftforge.client.resource.ISelectiveResourceReloadListener}, which selectively allows ++ * individual resource types being reloaded should rather be used where possible. ++ */ ++@Deprecated + @SideOnly(Side.CLIENT) + public interface IResourceManagerReloadListener + { diff --git a/patches/minecraft/net/minecraft/client/resources/SimpleReloadableResourceManager.java.patch b/patches/minecraft/net/minecraft/client/resources/SimpleReloadableResourceManager.java.patch index f2b81d4cb..042964f53 100644 --- a/patches/minecraft/net/minecraft/client/resources/SimpleReloadableResourceManager.java.patch +++ b/patches/minecraft/net/minecraft/client/resources/SimpleReloadableResourceManager.java.patch @@ -8,7 +8,7 @@ this.func_110543_a(); field_147967_a.info("Reloading ResourceManager: {}", (Object)field_130074_a.join(Iterables.transform(p_110541_1_, new Function() { -@@ -103,23 +104,32 @@ +@@ -103,23 +104,33 @@ for (IResourcePack iresourcepack : p_110541_1_) { @@ -36,6 +36,7 @@ for (IResourceManagerReloadListener iresourcemanagerreloadlistener : this.field_110546_b) { + resReload.step(iresourcemanagerreloadlistener.getClass()); ++ if (!net.minecraftforge.client.ForgeHooksClient.shouldUseVanillaReloadableListener(iresourcemanagerreloadlistener)) continue; // Forge: Selective reloading for vanilla listeners iresourcemanagerreloadlistener.func_110549_a(this); } + net.minecraftforge.fml.common.ProgressManager.pop(resReload); diff --git a/patches/minecraft/net/minecraft/client/settings/GameSettings.java.patch b/patches/minecraft/net/minecraft/client/settings/GameSettings.java.patch index c934f2e6a..1b373746b 100644 --- a/patches/minecraft/net/minecraft/client/settings/GameSettings.java.patch +++ b/patches/minecraft/net/minecraft/client/settings/GameSettings.java.patch @@ -21,10 +21,19 @@ this.field_74317_L.func_110434_K().func_110577_a(TextureMap.field_110575_b); this.field_74317_L.func_147117_R().func_174937_a(false, this.field_151442_I > 0); - this.field_74317_L.func_175603_A(); -+ this.needsResourceRefresh = true; // FORGE: fix for MC-64581 very laggy mipmap slider ++ this.needsBlockModelRefresh = true; // FORGE: fix for MC-64581 very laggy mipmap slider } } +@@ -361,7 +363,7 @@ + if (p_74306_1_ == GameSettings.Options.ANAGLYPH) + { + this.field_74337_g = !this.field_74337_g; +- this.field_74317_L.func_110436_a(); ++ net.minecraftforge.fml.client.FMLClientHandler.instance().refreshResources(net.minecraftforge.client.resource.VanillaResourceType.TEXTURES); + } + + if (p_74306_1_ == GameSettings.Options.GRAPHICS) @@ -1068,7 +1070,12 @@ { if (s1.equals("key_" + keybinding.func_151464_g())) @@ -82,13 +91,13 @@ + } + + // FORGE: fix for MC-64581 very laggy mipmap slider -+ private boolean needsResourceRefresh = false; ++ private boolean needsBlockModelRefresh = false; + public void onGuiClosed() + { -+ if (needsResourceRefresh) ++ if (needsBlockModelRefresh) + { -+ this.field_74317_L.func_175603_A(); -+ this.needsResourceRefresh = false; ++ net.minecraftforge.fml.client.FMLClientHandler.instance().scheduleResourcesRefresh(net.minecraftforge.client.resource.VanillaResourceType.MODELS); ++ this.needsBlockModelRefresh = false; + } + } + /******* Forge End ***********/ diff --git a/src/main/java/net/minecraftforge/client/CloudRenderer.java b/src/main/java/net/minecraftforge/client/CloudRenderer.java index 64a2d2e89..68a420eab 100644 --- a/src/main/java/net/minecraftforge/client/CloudRenderer.java +++ b/src/main/java/net/minecraftforge/client/CloudRenderer.java @@ -19,8 +19,12 @@ package net.minecraftforge.client; +import javax.annotation.Nonnull; import java.nio.ByteBuffer; +import java.util.function.Predicate; +import net.minecraftforge.client.resource.IResourceType; +import net.minecraftforge.client.resource.VanillaResourceType; import org.lwjgl.opengl.GL11; import net.minecraft.client.Minecraft; @@ -36,14 +40,14 @@ import net.minecraft.client.renderer.vertex.VertexBuffer; import net.minecraft.client.renderer.vertex.VertexFormat; import net.minecraft.client.resources.IReloadableResourceManager; import net.minecraft.client.resources.IResourceManager; -import net.minecraft.client.resources.IResourceManagerReloadListener; import net.minecraft.entity.Entity; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraftforge.common.ForgeModContainer; +import net.minecraftforge.client.resource.ISelectiveResourceReloadListener; -public class CloudRenderer implements IResourceManagerReloadListener +public class CloudRenderer implements ISelectiveResourceReloadListener { // Shared constants. private static final float PX_SIZE = 1 / 256F; @@ -478,8 +482,11 @@ public class CloudRenderer implements IResourceManagerReloadListener } @Override - public void onResourceManagerReload(IResourceManager resourceManager) + public void onResourceManagerReload(@Nonnull IResourceManager resourceManager, @Nonnull Predicate resourcePredicate) { - reloadTextures(); + if (resourcePredicate.test(VanillaResourceType.TEXTURES)) + { + reloadTextures(); + } } } diff --git a/src/main/java/net/minecraftforge/client/ForgeHooksClient.java b/src/main/java/net/minecraftforge/client/ForgeHooksClient.java index 88aad9aba..0a24c5ed5 100644 --- a/src/main/java/net/minecraftforge/client/ForgeHooksClient.java +++ b/src/main/java/net/minecraftforge/client/ForgeHooksClient.java @@ -40,6 +40,7 @@ import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.ISound; +import net.minecraft.client.audio.SoundHandler; import net.minecraft.client.audio.SoundManager; import net.minecraft.client.gui.BossInfoClient; import net.minecraft.client.gui.FontRenderer; @@ -47,11 +48,13 @@ import net.minecraft.client.gui.GuiMainMenu; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.model.ModelBiped; +import net.minecraft.client.renderer.BlockRendererDispatcher; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.EntityRenderer; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.RenderGlobal; +import net.minecraft.client.renderer.RenderItem; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.BlockFaceUV; import net.minecraft.client.renderer.block.model.IBakedModel; @@ -71,8 +74,13 @@ import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.client.renderer.vertex.VertexFormat; import net.minecraft.client.renderer.vertex.VertexFormatElement; import net.minecraft.client.renderer.vertex.VertexFormatElement.EnumUsage; +import net.minecraft.client.resources.FoliageColorReloadListener; +import net.minecraft.client.resources.GrassColorReloadListener; import net.minecraft.client.resources.I18n; +import net.minecraft.client.resources.IResourceManagerReloadListener; +import net.minecraft.client.resources.LanguageManager; import net.minecraft.client.settings.GameSettings; +import net.minecraft.client.util.SearchTreeManager; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.passive.EntityHorse; @@ -112,6 +120,9 @@ import net.minecraftforge.client.event.sound.PlaySoundEvent; import net.minecraftforge.client.model.ModelDynBucket; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.client.model.animation.Animation; +import net.minecraftforge.client.resource.IResourceType; +import net.minecraftforge.client.resource.SelectiveReloadStateHandler; +import net.minecraftforge.client.resource.VanillaResourceType; import net.minecraftforge.common.ForgeModContainer; import net.minecraftforge.common.ForgeVersion; import net.minecraftforge.common.ForgeVersion.Status; @@ -128,6 +139,8 @@ import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL20; +import java.util.function.Predicate; + import com.google.common.collect.Maps; public class ForgeHooksClient @@ -746,4 +759,26 @@ public class ForgeHooksClient if(texture == null) texture = horse.getHorseArmorType().getTextureName(); return texture; } + + public static boolean shouldUseVanillaReloadableListener(IResourceManagerReloadListener listener) + { + Predicate predicate = SelectiveReloadStateHandler.INSTANCE.get(); + + if (listener instanceof ModelManager || listener instanceof RenderItem) + return predicate.test(VanillaResourceType.MODELS); + else if (listener instanceof BlockRendererDispatcher || listener instanceof RenderGlobal) + return predicate.test(VanillaResourceType.MODELS); + else if (listener instanceof TextureManager || listener instanceof FontRenderer) + return predicate.test(VanillaResourceType.TEXTURES); + else if (listener instanceof FoliageColorReloadListener || listener instanceof GrassColorReloadListener) + return predicate.test(VanillaResourceType.TEXTURES); + else if (listener instanceof SoundHandler) + return predicate.test(VanillaResourceType.SOUNDS); + else if (listener instanceof EntityRenderer) + return predicate.test(VanillaResourceType.SHADERS); + else if (listener instanceof LanguageManager || listener instanceof SearchTreeManager) + return predicate.test(VanillaResourceType.LANGUAGES); + + return true; + } } diff --git a/src/main/java/net/minecraftforge/client/model/ICustomModelLoader.java b/src/main/java/net/minecraftforge/client/model/ICustomModelLoader.java index 3bd8d119c..f7a9d4eda 100644 --- a/src/main/java/net/minecraftforge/client/model/ICustomModelLoader.java +++ b/src/main/java/net/minecraftforge/client/model/ICustomModelLoader.java @@ -19,11 +19,30 @@ package net.minecraftforge.client.model; +import java.util.function.Predicate; + +import net.minecraftforge.client.resource.IResourceType; +import net.minecraftforge.client.resource.ISelectiveResourceReloadListener; +import net.minecraftforge.client.resource.VanillaResourceType; + +import net.minecraft.client.resources.IResourceManager; import net.minecraft.client.resources.IResourceManagerReloadListener; import net.minecraft.util.ResourceLocation; -public interface ICustomModelLoader extends IResourceManagerReloadListener +public interface ICustomModelLoader extends ISelectiveResourceReloadListener { + @Override + void onResourceManagerReload(IResourceManager resourceManager); + + @Override + default void onResourceManagerReload(IResourceManager resourceManager, Predicate resourcePredicate) + { + if (resourcePredicate.test(VanillaResourceType.MODELS)) + { + onResourceManagerReload(resourceManager); + } + } + /* * Checks if given model should be loaded by this loader. * Reading file contents is inadvisable, if possible decision should be made based on the location alone. diff --git a/src/main/java/net/minecraftforge/client/resource/IResourceType.java b/src/main/java/net/minecraftforge/client/resource/IResourceType.java new file mode 100644 index 000000000..44feb8c46 --- /dev/null +++ b/src/main/java/net/minecraftforge/client/resource/IResourceType.java @@ -0,0 +1,31 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2018. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.client.resource; + +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +/** + * Represents a generic type of reloadable resource. Used for resource reload filtering. + */ +@SideOnly(Side.CLIENT) +public interface IResourceType +{ +} diff --git a/src/main/java/net/minecraftforge/client/resource/ISelectiveResourceReloadListener.java b/src/main/java/net/minecraftforge/client/resource/ISelectiveResourceReloadListener.java new file mode 100644 index 000000000..cbc124617 --- /dev/null +++ b/src/main/java/net/minecraftforge/client/resource/ISelectiveResourceReloadListener.java @@ -0,0 +1,46 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2018. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.client.resource; + +import java.util.function.Predicate; + +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.resources.IResourceManagerReloadListener; + +public interface ISelectiveResourceReloadListener extends IResourceManagerReloadListener +{ + @Override + default void onResourceManagerReload(IResourceManager resourceManager) + { + // For compatibility, call the selective version from the non-selective function + onResourceManagerReload(resourceManager, SelectiveReloadStateHandler.INSTANCE.get()); + } + + /** + * A version of onResourceManager that selectively chooses {@link net.minecraftforge.client.resource.IResourceType}s + * to reload. + * When using this, the given predicate should be called to ensure the relevant resources should + * be reloaded at this time. + * + * @param resourceManager the resource manager being reloaded + * @param resourcePredicate predicate to test whether any given resource type should be reloaded + */ + void onResourceManagerReload(IResourceManager resourceManager, Predicate resourcePredicate); +} diff --git a/src/main/java/net/minecraftforge/client/resource/ReloadRequirements.java b/src/main/java/net/minecraftforge/client/resource/ReloadRequirements.java new file mode 100644 index 000000000..bb11eaf58 --- /dev/null +++ b/src/main/java/net/minecraftforge/client/resource/ReloadRequirements.java @@ -0,0 +1,57 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2018. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.client.resource; + +import java.util.Set; +import java.util.function.Predicate; + +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import com.google.common.collect.Sets; + +/** + * Holds methods to create standard predicates to select {@link IResourceType}s that should be reloaded. + */ +@SideOnly(Side.CLIENT) +public final class ReloadRequirements +{ + /** + * Creates a reload predicate accepting all resource types. + * + * @return a predicate accepting all types + */ + public static Predicate all() + { + return type -> true; + } + + /** + * Creates an inclusive reload predicate. Only given resource types will be loaded along with this. + * + * @param inclusion the set of resource types to be included in the reload + * @return an inclusion predicate based on the given types + */ + public static Predicate include(IResourceType... inclusion) + { + Set inclusionSet = Sets.newHashSet(inclusion); + return inclusionSet::contains; + } +} diff --git a/src/main/java/net/minecraftforge/client/resource/SelectiveReloadStateHandler.java b/src/main/java/net/minecraftforge/client/resource/SelectiveReloadStateHandler.java new file mode 100644 index 000000000..2b9a76264 --- /dev/null +++ b/src/main/java/net/minecraftforge/client/resource/SelectiveReloadStateHandler.java @@ -0,0 +1,76 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2018. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.client.resource; + +import javax.annotation.Nullable; +import java.util.function.Predicate; + +import net.minecraftforge.common.ForgeModContainer; + +/** + * Handles reload parameters for selective loaders. + */ +public enum SelectiveReloadStateHandler +{ + INSTANCE; + + @Nullable + private Predicate currentPredicate = null; + + /*** + * Pushes a resource type predicate for the current reload. + * Should only be called when initiating a resource reload. + * If a reload is already in progress when this is called, an exception will be thrown. + * + * @param resourcePredicate the resource requirement predicate for the current reload + */ + public void beginReload(Predicate resourcePredicate) + { + if (this.currentPredicate != null) + { + throw new IllegalStateException("Recursive resource reloading detected"); + } + + this.currentPredicate = resourcePredicate; + } + + /** + * Gets the current reload resource predicate for the initiated reload. + * + * @return the active reload resource predicate, or an accepting one if none in progress + */ + public Predicate get() + { + if (this.currentPredicate == null || !ForgeModContainer.selectiveResourceReloadEnabled) + { + return ReloadRequirements.all(); + } + + return this.currentPredicate; + } + + /** + * Finishes the current reload and deletes the previously added reload predicate. + */ + public void endReload() + { + this.currentPredicate = null; + } +} diff --git a/src/main/java/net/minecraftforge/client/resource/VanillaResourceType.java b/src/main/java/net/minecraftforge/client/resource/VanillaResourceType.java new file mode 100644 index 000000000..4ccb2a958 --- /dev/null +++ b/src/main/java/net/minecraftforge/client/resource/VanillaResourceType.java @@ -0,0 +1,58 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2018. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.client.resource; + +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +/** + * An enum of all {@link IResourceType}s used by the Vanilla game. These should be used if handling vanilla-related + * resources. + */ +@SideOnly(Side.CLIENT) +public enum VanillaResourceType implements IResourceType +{ + /** + * Used when block and item models are reloaded and rebaked. This also includes the texture-stitching from that + * phase. + */ + MODELS, + + /** + * Used when textures from the {@link net.minecraft.client.renderer.texture.TextureManager} are reloaded. Does not + * effect block or item textures on the texture atlas. + */ + TEXTURES, + + /** + * Used when all game sounds are reloaded. + */ + SOUNDS, + + /** + * Used when the current language is reloaded. + */ + LANGUAGES, + + /** + * Used when all shaders are reloaded. + */ + SHADERS, +} diff --git a/src/main/java/net/minecraftforge/client/resource/package-info.java b/src/main/java/net/minecraftforge/client/resource/package-info.java new file mode 100644 index 000000000..a2eabb79d --- /dev/null +++ b/src/main/java/net/minecraftforge/client/resource/package-info.java @@ -0,0 +1,26 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2018. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +package net.minecraftforge.client.resource; + +import javax.annotation.ParametersAreNonnullByDefault; + +import mcp.MethodsReturnNonnullByDefault; diff --git a/src/main/java/net/minecraftforge/common/ForgeModContainer.java b/src/main/java/net/minecraftforge/common/ForgeModContainer.java index e151288bf..ea50ec4ec 100644 --- a/src/main/java/net/minecraftforge/common/ForgeModContainer.java +++ b/src/main/java/net/minecraftforge/common/ForgeModContainer.java @@ -115,6 +115,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC public static boolean shouldSortRecipies = true; public static boolean disableVersionCheck = false; public static boolean forgeLightPipelineEnabled = true; + public static boolean selectiveResourceReloadEnabled = false; @Deprecated // TODO remove in 1.13 public static boolean replaceVanillaBucketModel = true; public static boolean zoomInMissingModelTextInGui = false; @@ -358,6 +359,12 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC prop.setLanguageKey("forge.configgui.forgeLightPipelineEnabled"); propOrder.add(prop.getName()); + prop = config.get(Configuration.CATEGORY_CLIENT, "selectiveResourceReloadEnabled", false, + "When enabled, makes specific reload tasks such as language changing quicker to run."); + selectiveResourceReloadEnabled = prop.getBoolean(false); + prop.setLanguageKey("forge.configgui.selectiveResourceReloadEnabled"); + propOrder.add(prop.getName()); + config.setCategoryPropertyOrder(CATEGORY_CLIENT, propOrder); if (config.hasChanged()) diff --git a/src/main/java/net/minecraftforge/fml/client/FMLClientHandler.java b/src/main/java/net/minecraftforge/fml/client/FMLClientHandler.java index d76fb572b..b9896bda0 100644 --- a/src/main/java/net/minecraftforge/fml/client/FMLClientHandler.java +++ b/src/main/java/net/minecraftforge/fml/client/FMLClientHandler.java @@ -33,6 +33,7 @@ import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; @@ -52,6 +53,7 @@ import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.resources.AbstractResourcePack; import net.minecraft.client.resources.FallbackResourceManager; import net.minecraft.client.resources.IReloadableResourceManager; +import net.minecraft.client.resources.IResource; import net.minecraft.client.resources.IResourcePack; import net.minecraft.client.resources.LegacyV2Adapter; import net.minecraft.client.resources.SimpleReloadableResourceManager; @@ -84,6 +86,9 @@ import net.minecraft.world.storage.SaveFormatOld; import net.minecraftforge.client.CloudRenderer; import net.minecraftforge.client.IRenderHandler; import net.minecraftforge.client.event.ModelRegistryEvent; +import net.minecraftforge.client.resource.IResourceType; +import net.minecraftforge.client.resource.ReloadRequirements; +import net.minecraftforge.client.resource.SelectiveReloadStateHandler; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.config.ConfigManager; import net.minecraftforge.common.util.CompoundDataFixer; @@ -133,6 +138,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.SetMultimap; import com.google.common.collect.Sets; import com.google.common.collect.Table; +import com.google.common.util.concurrent.ListenableFuture; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -1103,4 +1109,27 @@ public class FMLClientHandler implements IFMLSidedHandler } return getCloudRenderer().render(cloudTicks, partialTicks); } + + public void refreshResources(IResourceType... inclusion) + { + this.refreshResources(ReloadRequirements.include(inclusion)); + } + + // Wrapper around the existing refreshResources with given reload predicates + public void refreshResources(Predicate resourcePredicate) + { + SelectiveReloadStateHandler.INSTANCE.beginReload(resourcePredicate); + this.client.refreshResources(); + SelectiveReloadStateHandler.INSTANCE.endReload(); + } + + public ListenableFuture scheduleResourcesRefresh(IResourceType... inclusion) + { + return this.scheduleResourcesRefresh(ReloadRequirements.include(inclusion)); + } + + public ListenableFuture scheduleResourcesRefresh(Predicate resourcePredicate) + { + return this.client.addScheduledTask(() -> this.refreshResources(resourcePredicate)); + } } diff --git a/src/main/resources/assets/forge/lang/en_US.lang b/src/main/resources/assets/forge/lang/en_US.lang index d475dd248..6e367f265 100644 --- a/src/main/resources/assets/forge/lang/en_US.lang +++ b/src/main/resources/assets/forge/lang/en_US.lang @@ -87,6 +87,8 @@ forge.configgui.zoomInMissingModelTextInGui=Zoom in Missing model text in the GU forge.configgui.disableStairSlabCulling.tooltip=Enable this if you see through blocks touching stairs/slabs with your resource pack. forge.configgui.alwaysSetupTerrainOffThread=Force threaded chunk rendering forge.configgui.alwaysSetupTerrainOffThread.tooltip=Enable forge to queue all chunk updates to the Chunk Update thread. May increase FPS significantly, but may also cause weird rendering lag. Not recommended for computers without a significant number of cores available. +forge.configgui.selectiveResourceReloadEnabled=Enable Selective Resource Loading +forge.configgui.selectiveResourceReloadEnabled.tooltip=When enabled, makes specific reload tasks such as language changing quicker to run. forge.configgui.modID.tooltip=The mod ID that you want to define override settings for. forge.configgui.modID=Mod ID