From 6962678804806756019bd4e157c6ff50633cafd4 Mon Sep 17 00:00:00 2001 From: Ben Staddon Date: Thu, 18 Jan 2018 20:44:14 +0000 Subject: [PATCH] Make async chunk loading a config option (#4544) --- .../chunk/storage/AnvilChunkLoader.java.patch | 22 ++++++++++--------- .../world/gen/ChunkProviderServer.java.patch | 6 ++--- .../common/ForgeChunkManager.java | 9 ++++++++ .../resources/assets/forge/lang/en_US.lang | 2 ++ 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/patches/minecraft/net/minecraft/world/chunk/storage/AnvilChunkLoader.java.patch b/patches/minecraft/net/minecraft/world/chunk/storage/AnvilChunkLoader.java.patch index 9bce5f4e5..bafb37b69 100644 --- a/patches/minecraft/net/minecraft/world/chunk/storage/AnvilChunkLoader.java.patch +++ b/patches/minecraft/net/minecraft/world/chunk/storage/AnvilChunkLoader.java.patch @@ -1,6 +1,6 @@ --- ../src-base/minecraft/net/minecraft/world/chunk/storage/AnvilChunkLoader.java +++ ../src-work/minecraft/net/minecraft/world/chunk/storage/AnvilChunkLoader.java -@@ -49,9 +49,30 @@ +@@ -49,9 +49,31 @@ this.field_193416_e = p_i46673_2_; } @@ -26,12 +26,13 @@ + return null; + } + ++ @Nullable + public Object[] loadChunk__Async(World p_75815_1_, int p_75815_2_, int p_75815_3_) throws IOException + { ChunkPos chunkpos = new ChunkPos(p_75815_2_, p_75815_3_); NBTTagCompound nbttagcompound = this.field_75828_a.get(chunkpos); -@@ -67,7 +88,7 @@ +@@ -67,7 +89,7 @@ nbttagcompound = this.field_193416_e.func_188257_a(FixTypes.CHUNK, CompressedStreamTools.func_74794_a(datainputstream)); } @@ -40,7 +41,7 @@ } public boolean func_191063_a(int p_191063_1_, int p_191063_2_) -@@ -80,6 +101,12 @@ +@@ -80,6 +102,13 @@ @Nullable protected Chunk func_75822_a(World p_75822_1_, int p_75822_2_, int p_75822_3_, NBTTagCompound p_75822_4_) { @@ -48,12 +49,13 @@ + return data != null ? (Chunk)data[0] : null; + } + ++ @Nullable + protected Object[] checkedReadChunkFromNBT__Async(World p_75822_1_, int p_75822_2_, int p_75822_3_, NBTTagCompound p_75822_4_) + { if (!p_75822_4_.func_150297_b("Level", 10)) { field_151505_a.error("Chunk file at {},{} is missing level data, skipping", Integer.valueOf(p_75822_2_), Integer.valueOf(p_75822_3_)); -@@ -103,10 +130,29 @@ +@@ -103,10 +132,29 @@ field_151505_a.error("Chunk file at {},{} is in the wrong location; relocating. (Expected {}, {}, got {}, {})", Integer.valueOf(p_75822_2_), Integer.valueOf(p_75822_3_), Integer.valueOf(p_75822_2_), Integer.valueOf(p_75822_3_), Integer.valueOf(chunk.field_76635_g), Integer.valueOf(chunk.field_76647_h)); nbttagcompound.func_74768_a("xPos", p_75822_2_); nbttagcompound.func_74768_a("zPos", p_75822_3_); @@ -84,7 +86,7 @@ } } } -@@ -121,7 +167,10 @@ +@@ -121,7 +169,10 @@ NBTTagCompound nbttagcompound1 = new NBTTagCompound(); nbttagcompound.func_74782_a("Level", nbttagcompound1); nbttagcompound.func_74768_a("DataVersion", 1343); @@ -95,7 +97,7 @@ this.func_75824_a(p_75816_2_.func_76632_l(), nbttagcompound); } catch (Exception exception) -@@ -305,11 +354,19 @@ +@@ -305,11 +356,19 @@ { NBTTagCompound nbttagcompound2 = new NBTTagCompound(); @@ -115,7 +117,7 @@ } } -@@ -318,8 +375,16 @@ +@@ -318,8 +377,16 @@ for (TileEntity tileentity : p_75820_1_.func_177434_r().values()) { @@ -132,7 +134,7 @@ } p_75820_3_.func_74782_a("TileEntities", nbttaglist2); -@@ -345,6 +410,18 @@ +@@ -345,6 +412,18 @@ p_75820_3_.func_74782_a("TileTicks", nbttaglist3); } @@ -151,7 +153,7 @@ } private Chunk func_75823_a(World p_75823_1_, NBTTagCompound p_75823_2_) -@@ -388,6 +465,16 @@ +@@ -388,6 +467,16 @@ chunk.func_76616_a(p_75823_2_.func_74770_j("Biomes")); } @@ -168,7 +170,7 @@ NBTTagList nbttaglist1 = p_75823_2_.func_150295_c("Entities", 10); for (int j1 = 0; j1 < nbttaglist1.func_74745_c(); ++j1) -@@ -431,8 +518,6 @@ +@@ -431,8 +520,6 @@ p_75823_1_.func_180497_b(new BlockPos(nbttagcompound3.func_74762_e("x"), nbttagcompound3.func_74762_e("y"), nbttagcompound3.func_74762_e("z")), block, nbttagcompound3.func_74762_e("t"), nbttagcompound3.func_74762_e("p")); } } diff --git a/patches/minecraft/net/minecraft/world/gen/ChunkProviderServer.java.patch b/patches/minecraft/net/minecraft/world/gen/ChunkProviderServer.java.patch index 67dfb4c5c..e20daa486 100644 --- a/patches/minecraft/net/minecraft/world/gen/ChunkProviderServer.java.patch +++ b/patches/minecraft/net/minecraft/world/gen/ChunkProviderServer.java.patch @@ -4,7 +4,7 @@ public final IChunkLoader field_73247_e; public final Long2ObjectMap field_73244_f = new Long2ObjectOpenHashMap(8192); public final WorldServer field_73251_h; -+ private Set loadingChunks = com.google.common.collect.Sets.newHashSet(); ++ private final Set loadingChunks = com.google.common.collect.Sets.newHashSet(); public ChunkProviderServer(WorldServer p_i46838_1_, IChunkLoader p_i46838_2_, IChunkGenerator p_i46838_3_) { @@ -17,7 +17,7 @@ + } + @Nullable -+ public Chunk loadChunk(int p_186028_1_, int p_186028_2_, Runnable runnable) ++ public Chunk loadChunk(int p_186028_1_, int p_186028_2_, @Nullable Runnable runnable) + { + Chunk chunk = this.func_186026_b(p_186028_1_, p_186028_2_); if (chunk == null) @@ -44,7 +44,7 @@ + else + { + net.minecraft.world.chunk.storage.AnvilChunkLoader loader = (net.minecraft.world.chunk.storage.AnvilChunkLoader) this.field_73247_e; -+ if (runnable == null) ++ if (runnable == null || !net.minecraftforge.common.ForgeChunkManager.asyncChunkLoading) + chunk = net.minecraftforge.common.chunkio.ChunkIOExecutor.syncChunkLoad(this.field_73251_h, loader, this, p_186028_1_, p_186028_2_); + else if (loader.func_191063_a(p_186028_1_, p_186028_2_)) + { diff --git a/src/main/java/net/minecraftforge/common/ForgeChunkManager.java b/src/main/java/net/minecraftforge/common/ForgeChunkManager.java index 274ac7f6a..d87e7057d 100644 --- a/src/main/java/net/minecraftforge/common/ForgeChunkManager.java +++ b/src/main/java/net/minecraftforge/common/ForgeChunkManager.java @@ -113,6 +113,8 @@ public class ForgeChunkManager private static int playerTicketLength; private static int dormantChunkCacheSize; + public static boolean asyncChunkLoading; + public static final List MOD_PROP_ORDER = new ArrayList(2); private static Set warnedMods = Sets.newHashSet(); @@ -1101,6 +1103,13 @@ public class ForgeChunkManager propOrder.add("dormantChunkCacheSize"); FMLLog.log.info("Configured a dormant chunk cache size of {}", temp.getInt(0)); + temp = config.get("defaults", "asyncChunkLoading", true); + temp.setComment("Load chunks asynchronously for players, reducing load on the server thread.\n" + + "Can be disabled to help troubleshoot chunk loading issues."); + temp.setLanguageKey("forge.configgui.asyncChunkLoading"); + asyncChunkLoading = temp.getBoolean(true); + propOrder.add("asyncChunkLoading"); + config.setCategoryPropertyOrder("defaults", propOrder); config.addCustomCategoryComment(ForgeVersion.MOD_ID, "Sample mod specific control section.\n" + diff --git a/src/main/resources/assets/forge/lang/en_US.lang b/src/main/resources/assets/forge/lang/en_US.lang index 38e3b60cc..ba6b6c64b 100644 --- a/src/main/resources/assets/forge/lang/en_US.lang +++ b/src/main/resources/assets/forge/lang/en_US.lang @@ -84,6 +84,8 @@ forge.configgui.alwaysSetupTerrainOffThread.tooltip=Enable forge to queue all ch forge.configgui.modID.tooltip=The mod ID that you want to define override settings for. forge.configgui.modID=Mod ID +forge.configgui.asyncChunkLoading=Async Chunk Loading +forge.configgui.asyncChunkLoading.tooltip=Load chunks asynchronously for players, reducing load on the server thread. Can be disabled to help troubleshoot chunk loading issues. forge.configgui.dormantChunkCacheSize.tooltip=Unloaded chunks can first be kept in a dormant cache for quicker loading times. Specify the size (in chunks) of that cache here. forge.configgui.dormantChunkCacheSize=Dormant Chunk Cache Size forge.configgui.enableModOverrides.tooltip=Enable this setting to allow custom per-mod settings to be defined.