From 60491a9c698d3bc797c14c6f17a6d272db5146e6 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Wed, 13 Sep 2023 21:50:46 -0400 Subject: [PATCH 01/11] Update gradle.yml --- .github/workflows/gradle.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index b4d56c53..48f6ca92 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -21,12 +21,22 @@ jobs: with: distribution: 'temurin' java-version: 17 - - name: Build ModernFix using Gradle + - name: Setup Gradle uses: gradle/gradle-build-action@v2 with: cache-read-only: ${{ !startsWith(github.ref, 'refs/heads/1.') }} gradle-home-cache-cleanup: true - arguments: build + - name: Setup project Loom cache + uses: actions/cache@v3 + with: + path: | + .gradle/loom-cache + key: ${{ runner.os }}-gradle-${{ hashFiles('**/gradle.properties', '**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: ${{ runner.os }}-gradle- + - name: Build ModernFix + run: | + chmod +x gradlew + ./gradlew build - name: Upload Artifacts to GitHub uses: actions/upload-artifact@v3 with: From e94f1481ae36e536468e03fe84def34bbd368e60 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Fri, 15 Sep 2023 09:23:48 -0400 Subject: [PATCH 02/11] Don't use Parchment in testmod --- fabric/testmod/build.gradle | 3 --- 1 file changed, 3 deletions(-) diff --git a/fabric/testmod/build.gradle b/fabric/testmod/build.gradle index 6fd2d983..fd7f0a5e 100644 --- a/fabric/testmod/build.gradle +++ b/fabric/testmod/build.gradle @@ -18,9 +18,6 @@ dependencies { minecraft "com.mojang:minecraft:${rootProject.minecraft_version}" mappings loom.layered() { officialMojangMappings() - if(rootProject.hasProperty("parchment_version")) { - parchment("org.parchmentmc.data:parchment-${minecraft_version}:${parchment_version}@zip") - } } modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" From a0c5c90c8d6854393fe32708f7367c8714218883 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Fri, 15 Sep 2023 09:32:30 -0400 Subject: [PATCH 03/11] Prevent crash with mods calling getFluidState recursively The returned fluid is meaningless, but vanilla doesn't crash here Fixes #238 --- .../BlockStateBaseMixin.java | 15 +++++++++++++-- .../level/block/state/BlockStateCacheTest.java | 16 ++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockStateBaseMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockStateBaseMixin.java index 2c209d88..2c217d0b 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockStateBaseMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockStateBaseMixin.java @@ -87,8 +87,19 @@ public abstract class BlockStateBaseMixin extends StateHolder // don't generate the full cache here as mods will iterate for the fluid state a lot // assume blockstates will not change their contained fluidstate at runtime more than once // this is how Lithium's implementation used to work, so it should be fine - if(this.cacheInvalid && this.fluidState == MFIX$VANILLA_DEFAULT_FLUID) - this.fluidState = this.owner.getFluidState(this.asState()); + if(this.cacheInvalid && this.fluidState == MFIX$VANILLA_DEFAULT_FLUID) { + synchronized (BlockBehaviour.BlockStateBase.class) { + if(!buildingCache) { + buildingCache = true; + try { + this.fluidState = this.owner.getFluidState(this.asState()); + } finally { + buildingCache = false; + } + } + } + + } return this.fluidState; } diff --git a/fabric/src/test/java/net/minecraft/world/level/block/state/BlockStateCacheTest.java b/fabric/src/test/java/net/minecraft/world/level/block/state/BlockStateCacheTest.java index 3e54137b..26bc9c18 100644 --- a/fabric/src/test/java/net/minecraft/world/level/block/state/BlockStateCacheTest.java +++ b/fabric/src/test/java/net/minecraft/world/level/block/state/BlockStateCacheTest.java @@ -4,6 +4,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.level.EmptyBlockGetter; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.material.FluidState; import org.embeddedt.modernfix.duck.IBlockState; import org.embeddedt.modernfix.testing.util.BootstrapMinecraft; import org.junit.jupiter.api.*; @@ -74,4 +75,19 @@ public class BlockStateCacheTest { } } } + + @Test + @Order(5) + public void checkRecursiveFluidState() { + Block b = new Block(BlockBehaviour.Properties.copy(Blocks.STONE)) { + @Override + public FluidState getFluidState(BlockState state) { + return state.getFluidState(); + } + }; + BlockState state = b.getStateDefinition().any(); + ((IBlockState)state).clearCache(); + // this should not throw + state.getFluidState(); + } } From 7d9f110f273ad41c57c8622ae0b27c223252925e Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 31 Aug 2023 11:49:15 -0400 Subject: [PATCH 04/11] Fix use of relative paths for changelog --- build.gradle | 4 ++-- .../src/main/groovy/modernfix.platform-conventions.gradle | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 95e3d5b8..f943a7a3 100644 --- a/build.gradle +++ b/build.gradle @@ -50,8 +50,8 @@ tasks.register('generateChangelog', se.bjurr.gitchangelog.plugin.gradle.GitChang fromRef = theVersionRef - file = new File("CHANGELOG.md"); - templateContent = new File('gradle/changelog.mustache').getText('UTF-8').replace("[[modernFixVersionRef]]", theVersionRef); + file = new File("${rootDir}/CHANGELOG.md"); + templateContent = new File("${rootDir}/gradle/changelog.mustache").getText('UTF-8').replace("[[modernFixVersionRef]]", theVersionRef); toCommit = "HEAD"; } diff --git a/buildSrc/src/main/groovy/modernfix.platform-conventions.gradle b/buildSrc/src/main/groovy/modernfix.platform-conventions.gradle index 5753965e..a989c5ed 100644 --- a/buildSrc/src/main/groovy/modernfix.platform-conventions.gradle +++ b/buildSrc/src/main/groovy/modernfix.platform-conventions.gradle @@ -40,7 +40,7 @@ curseforge { apiKey = System.getenv("CURSEFORGE_TOKEN") project { id = "790626" - changelog = file('../CHANGELOG.md') + changelog = file("${rootDir}/CHANGELOG.md") changelogType = "markdown" releaseType = isBeta ? "beta" : "release" addGameVersion project.name.capitalize() From fe942c90df0ba09cf815193d7a800b55e8e5580b Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 17 Sep 2023 12:30:20 -0400 Subject: [PATCH 05/11] More documentation Related: #232 --- common/src/main/resources/assets/modernfix/lang/en_us.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/common/src/main/resources/assets/modernfix/lang/en_us.json b/common/src/main/resources/assets/modernfix/lang/en_us.json index 29d2e454..ec27bf0f 100644 --- a/common/src/main/resources/assets/modernfix/lang/en_us.json +++ b/common/src/main/resources/assets/modernfix/lang/en_us.json @@ -114,5 +114,10 @@ "modernfix.option.mixin.perf.twilightforest.structure_spawn_fix": "Fixes lag caused by Twilight Forest worldgen checking structures very inefficiently", "modernfix.option.mixin.perf.fast_forge_dummies": "Speeds up Forge registry freezing during launch by using a faster code path", "modernfix.option.mixin.perf.tag_id_caching": "Speeds up uses of tag entries by caching the location object instead of recreating it every time", - "modernfix.option.mixin.feature.disable_unihex_font": "Remove the Unicode font, saves 10MB but causes special characters to no longer render" + "modernfix.option.mixin.feature.disable_unihex_font": "Remove the Unicode font, saves 10MB but causes special characters to no longer render", + "modernfix.option.mixin.bugfix.world_leaks": "Reduces the memory usage of old client-side worlds that aren't needed after switching dimensions. These are normally garbage collected in vanilla, but mods sometimes retain references to them.", + "modernfix.option.mixin.perf.compact_mojang_registries": "(Fabric) Experimental option that reduces the memory usage of registries by roughly 50%. Not useful in most modpacks unless they contain millions of blocks and items.", + "modernfix.option.mixin.perf.dynamic_block_codecs": "Avoids storing a codec for every block(state) and instead generates and caches it on the fly when needed. Generally not worth enabling unless you have a million blocks/items.", + "modernfix.option.mixin.perf.faster_command_suggestions": "Mitigate lag when there are hundreds of thousands of suggestions while typing a command", + "modernfix.option.mixin.perf.mojang_registry_size": "Fixes an issue causing registration of blocks/items to slow down proportional to the number already registered. This improves startup time." } From bd1ca9ce94ed717a69cecf48c25862e6817f521c Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 17 Sep 2023 13:00:54 -0400 Subject: [PATCH 06/11] Disable reduce_blockstate_cache_rebuilds if dev env is not Mojmap This is simpler than implementing remapping Closes #229 --- .../core/config/ModernFixEarlyConfig.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java index c1eed340..67af3710 100644 --- a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java +++ b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java @@ -229,6 +229,21 @@ public class ModernFixEarlyConfig { if(isFabric) { disableIfModPresent("mixin.bugfix.packet_leak", "memoryleakfix"); } + + checkBlockstateCacheRebuilds(); + } + + private void checkBlockstateCacheRebuilds() { + if(!ModernFixPlatformHooks.INSTANCE.isDevEnv()) + return; + try { + if(ModernFixEarlyConfig.class.getResource("/net/minecraft/world/level/Level.class") == null) { + LOGGER.warn("We are in a non-Mojmap dev environment. Disabling blockstate cache patch"); + this.options.get("mixin.perf.reduce_blockstate_cache_rebuilds").addModOverride(false, "[not mojmap]"); + } + } catch(Throwable e) { + e.printStackTrace(); + } } private void disableIfModPresent(String configName, String... ids) { From bdd12f18027f7cf15b8d5a8300a46b342683d782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=B6=E6=99=BA=E4=B9=83=E5=8F=8D=E4=B8=8D=E8=83=BD?= =?UTF-8?q?=E5=8F=8A?= <100760086+qznfbnj@users.noreply.github.com> Date: Mon, 18 Sep 2023 22:05:22 +0800 Subject: [PATCH 07/11] Update zh_cn.json (#240) --- .../main/resources/assets/modernfix/lang/zh_cn.json | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/common/src/main/resources/assets/modernfix/lang/zh_cn.json b/common/src/main/resources/assets/modernfix/lang/zh_cn.json index 11eba3e2..457d4a01 100644 --- a/common/src/main/resources/assets/modernfix/lang/zh_cn.json +++ b/common/src/main/resources/assets/modernfix/lang/zh_cn.json @@ -42,6 +42,7 @@ "modernfix.option.mixin.perf.deduplicate_location": "全版本共有,但由于会影响加载时间,默认禁用。对资源位置的命名空间和路径进行去重。这节省了内存,但也大大增加了新资源位置的构造成本。", "modernfix.option.mixin.perf.dynamic_dfu": "全版本共有。修改了DFU的初始化,使其仅在第一次需要升级数据时加载。这听起来类似DFU载入优化,但实现方式截然不同,因为它能避免加载§o任何§rDFU类/数据结构,而DFU载入优化只是禁用其规则优化。本质上说,这是一个DataFixerSlayer的安全版本,因为它仍然会在需要时加载DFU。\n\n即使启用了这个选项,你也应该继续使用DFU载入优化,否则DFU规则优化依然会导致卡顿。", "modernfix.option.mixin.perf.dynamic_resources": "全版本共有。详见https://github.com/Kasualix/ModernFix/wiki/动态资源加载---常见问题解答。", + "modernfix.option.mixin.perf.dynamic_sounds": "全版本共有。允许游戏卸载声音,而不是在加载声音后无限期地保留它们。", "modernfix.option.mixin.perf.dynamic_structure_manager": "全版本共有。允许游戏在结构生成结束后卸载结构文件,而非让它们永远处于已加载状态。", "modernfix.option.mixin.perf.fast_registry_validation": "全版本共有。每次验证注册时,Forge都会通过反射来查找一个方法,这完全没必要。这个补丁简单地缓存了方法的返回值,因为它每次都是一样的。", "modernfix.option.mixin.perf.faster_font_loading": "全版本共有。优化字体渲染器,以更快地加载字体,加快资源重载速度。", @@ -53,7 +54,7 @@ "modernfix.option.mixin.perf.model_optimizations": "全版本共有。通过优化以加快模型加载过程。", "modernfix.option.mixin.perf.nbt_memory_usage": "全版本共有。对复合NBT标签使用一个更加高效的支持映射(backing map),从而消除重复键名,对小型复合 NBT 也使用数组映射。这减少了在内存中存储许多复合NBT标签的开销。", "modernfix.option.mixin.perf.nuke_empty_chunk_sections": "仅1.16。灵感来自氢(Hydrogen)模组。将存储充满空气的区块部分标记为空(empty),避免在内存中存储它们。", - "modernfix.option.mixin.perf.reduce_blockstate_cache_rebuilds": "全版本共有。§l一项关键优化。§r较新的Minecraft(1.12以上)实现了一个方块状态缓存系统,它可以缓存方块状态的常用信息,譬如其是否为固体方块,它的碰撞箱形状等等。原版中重建此缓存非常快(只要一两秒钟),但在安装了许多模组后就相当慢了,因为游戏中多了很多其它的方块状态,它们的缓存都需要被其重建。\n\n在Forge的影响下,这个问题变得更加严重,因为缓存会在很多地方重建,但这些数据在下一次重建前几乎肯定不会被用到。至于在哪儿,比如,在到达主菜单之前(在“Freezing data”阶段),以及在加载世界时(会出现很多次!)。\n\n通过让缓存重建转为惰性,现代化修复解决了这个性能瓶颈问题。每个方块状态在第一次访问数据时都会重建其缓存。无论何时,原版或Forge试图重建所有方块状态缓存的行为都会被重定向,变成简单地使每个方块状态的缓存失效。\n\n此项优化不应该对启动后的TPS产生任何影响。", + "modernfix.option.mixin.perf.reduce_blockstate_cache_rebuilds": "全版本共有。§l一项关键优化。§r较新的Minecraft(1.12以上)实现了一个方块状态缓存系统,它可以缓存方块状态的常用信息,譬如其是否为固体方块,它的碰撞箱形状等等。原版中重建此缓存非常快(只要一两秒钟),但在安装了许多模组后就相当慢了,因为游戏中多了很多其它的方块状态,它们的缓存都需要被其重建。\n\n在Forge的影响下,这个问题变得更加严重,因为缓存会在很多地方重建,但这些数据在下一次重建前几乎肯定不会被用到。至于在哪儿,比如,在到达主菜单之前(在“Freezing data”阶段),以及在加载世界时(会出现很多次!)。\n\n通过让缓存重建转为惰性,现代化修复解决了这个性能瓶颈问题。每个方块状态在第一次访问数据时都会重建其缓存。无论何时,原版或Forge试图重建所有方块状态缓存的行为都会被重定向,变成简单地使每个方块状态的缓存失效。\n\n此项优化应该不会对启动后的TPS产生任何影响。", "modernfix.option.mixin.perf.remove_biome_temperature_cache": "全版本共有。移除生物群系温度缓存,以减少内存占用,就像新版本的锂所做的那样。", "modernfix.option.mixin.perf.resourcepacks": "全版本共有。§l一项关键优化。§r高版本的启动严重受到文件系统访问的瓶颈限制。资源包经常接受到很多请求,要列出资源或检查一项给定的资源是否存在,而每次请求都会调用一个效率极低的文件API。\n\n现代化修复通过简单地缓存模组和原版提供的所有资源的列表,完全消除了此处的大部分瓶颈。缓存在资源重载时会进行重建(除了原版资源,因为它们在游戏运行时不应改变)。\n\n高清修复不能正确加载它的连接纹理(CTM)资源,除此之外此补丁没有已知的兼容问题。不过,我不建议在任何情况下使用高清修复,因为它本身就会增加几分钟的启动时间,而且根本没有与现代化修复进行过任何测试。", "modernfix.option.mixin.perf.reuse_datapacks": "仅1.16。试图尽可能跳过数据包重载,来加快单人世界切换/重进时的速度。可能会导致一些模组的兼容性问题,但目前默认启用。", @@ -114,5 +115,10 @@ "modernfix.option.mixin.perf.twilightforest.structure_spawn_fix": "针对暮色森林模组,修复了其世界生成检查结构效率极低导致卡顿的问题", "modernfix.option.mixin.perf.fast_forge_dummies": "使用更快的代码路径,加快启动时Forge注册表的冻结速度", "modernfix.option.mixin.perf.tag_id_caching": "缓存位置对象,不再每次都重新创建它,这可以加快标签条目的使用速度", - "modernfix.option.mixin.feature.disable_unihex_font": "删除Unicode字体,可以节省10MB内存,但会导致特殊字符不再渲染" + "modernfix.option.mixin.feature.disable_unihex_font": "删除Unicode字体,可以节省10MB内存,但会导致特殊字符不再渲染", + "modernfix.option.mixin.bugfix.world_leaks": "减少切换维度后不需要的旧客户端世界的内存占用。这部分内存在原版中通常会被垃圾回收,但有时模组会保留对它们的引用。", + "modernfix.option.mixin.perf.compact_mojang_registries": "(Fabric)实验性选项,可将注册表的内存占用减少约 50%。在大多数整合包中没什么用,除非它们包含数百万个方块和物品。", + "modernfix.option.mixin.perf.dynamic_block_codecs": "不再给每个方块(状态)都存储一个编解码器,只在需要时动态生成、缓存它。通常不值得启用,除非你有一百万个方块/物品。", + "modernfix.option.mixin.perf.faster_command_suggestions": "在输入命令时,若有数十万个建议,可以缓解卡顿。", + "modernfix.option.mixin.perf.mojang_registry_size": "修复了一个问题,它会导致方块/物品的注册速度减慢,减慢的程度与已注册的数量成正比。这缩短了启动时间。" } From 7ff300d8dfdd5b0704b18f96bcc622050d98c359 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Wed, 20 Sep 2023 17:58:25 -0400 Subject: [PATCH 08/11] Add Vampirism to mods requiring fallback model iterator Related: #242 --- .../modernfix/forge/dynresources/ModelBakeEventHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java b/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java index f89d1c20..fed07281 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java @@ -27,7 +27,7 @@ import java.util.*; */ public class ModelBakeEventHelper { // TODO: make into config option - private static final Set INCOMPATIBLE_MODS = ImmutableSet.of("industrialforegoing"); + private static final Set INCOMPATIBLE_MODS = ImmutableSet.of("industrialforegoing", "vampirism"); private final Map modelRegistry; private final Set topLevelModelLocations; private final MutableGraph dependencyGraph; From 5c21a98c7f44b34f76eb824ff7e866943d8e1265 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 17 Sep 2023 20:38:29 -0400 Subject: [PATCH 09/11] New stylized logo by CelestialAbyss --- common/src/main/resources/icon.png | Bin 17481 -> 15363 bytes doc/logo.svg | 208 ++++++++++++++++++++++++++++ doc/logo_transparent.svg | 209 +++++++++++++++++++++++++++++ 3 files changed, 417 insertions(+) create mode 100644 doc/logo.svg create mode 100644 doc/logo_transparent.svg diff --git a/common/src/main/resources/icon.png b/common/src/main/resources/icon.png index a32ac9a967654d24bd8f836dcc68560d6c4e0d5b..450e09f58bbd9ccfae6366e75b671c01e93da932 100644 GIT binary patch literal 15363 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 U3LX7+4go)MkCmj#9~lPyA8Mb%T>t<8 diff --git a/doc/logo.svg b/doc/logo.svg new file mode 100644 index 00000000..fb9be4f9 --- /dev/null +++ b/doc/logo.svg @@ -0,0 +1,208 @@ + + + + diff --git a/doc/logo_transparent.svg b/doc/logo_transparent.svg new file mode 100644 index 00000000..48a1bff4 --- /dev/null +++ b/doc/logo_transparent.svg @@ -0,0 +1,209 @@ + + + + From 7b1d9ff8bba98ed75aa250a19f54727f4279dede Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Fri, 22 Sep 2023 22:04:55 -0400 Subject: [PATCH 10/11] Improve Async Locator backport for 1.16 --- .../async_locator/SetNameFunctionMixin.java | 26 +++++++++++ .../mixin/perf/async_locator/SlotMixin.java | 28 +++++++++++ .../forge/structure/logic/CommonLogic.java | 46 +++++++++++++++++-- .../logic/ExplorationMapFunctionLogic.java | 34 ++++++++++++-- 4 files changed, 127 insertions(+), 7 deletions(-) create mode 100644 forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/SetNameFunctionMixin.java create mode 100644 forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/SlotMixin.java diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/SetNameFunctionMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/SetNameFunctionMixin.java new file mode 100644 index 00000000..9f215c86 --- /dev/null +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/SetNameFunctionMixin.java @@ -0,0 +1,26 @@ +package org.embeddedt.modernfix.forge.mixin.perf.async_locator; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.storage.loot.functions.SetNameFunction; +import org.embeddedt.modernfix.forge.structure.logic.CommonLogic; +import org.embeddedt.modernfix.forge.structure.logic.ExplorationMapFunctionLogic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(SetNameFunction.class) +public class SetNameFunctionMixin { + @Redirect( + method = "run", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/item/ItemStack;setHoverName(Lnet/minecraft/network/chat/Component;)Lnet/minecraft/world/item/ItemStack;" + ) + ) + public ItemStack deferSetName(ItemStack stack, Component name) { + if (CommonLogic.isEmptyPendingMap(stack)) + ExplorationMapFunctionLogic.cacheName(stack, name); + return stack; + } +} diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/SlotMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/SlotMixin.java new file mode 100644 index 00000000..4e6f8b66 --- /dev/null +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/async_locator/SlotMixin.java @@ -0,0 +1,28 @@ +package org.embeddedt.modernfix.forge.mixin.perf.async_locator; + +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.embeddedt.modernfix.forge.structure.logic.CommonLogic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(Slot.class) +public abstract class SlotMixin { + @Shadow + public abstract ItemStack getItem(); + + @Inject( + method = "mayPickup", + at = @At(value = "HEAD"), + cancellable = true + ) + public void preventPickupOfPendingExplorationMap(Player player, CallbackInfoReturnable cir) { + if (CommonLogic.isEmptyPendingMap(getItem())) { + cir.setReturnValue(false); + } + } +} diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/structure/logic/CommonLogic.java b/forge/src/main/java/org/embeddedt/modernfix/forge/structure/logic/CommonLogic.java index 84a2460f..96915589 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/structure/logic/CommonLogic.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/structure/logic/CommonLogic.java @@ -1,6 +1,8 @@ package org.embeddedt.modernfix.forge.structure.logic; import net.minecraft.core.BlockPos; +import net.minecraft.nbt.ByteTag; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -15,6 +17,9 @@ import net.minecraft.world.level.saveddata.maps.MapItemSavedData; import org.embeddedt.modernfix.forge.mixin.perf.async_locator.MapItemAccess; public class CommonLogic { + private static final String MAP_HOVER_NAME_KEY = "menu.working"; + private static final String KEY_LOCATING = "asynclocator.locating"; + private CommonLogic() {} /** @@ -24,10 +29,23 @@ public class CommonLogic { */ public static ItemStack createEmptyMap() { ItemStack stack = new ItemStack(Items.FILLED_MAP); - stack.setHoverName(new TranslatableComponent("asynclocator.map.locating")); + stack.setHoverName(new TranslatableComponent(MAP_HOVER_NAME_KEY)); + stack.addTagElement(KEY_LOCATING, ByteTag.ONE); return stack; } + /** + * Returns true if the stack is an empty FILLED_MAP item with the hover tooltip name stating that it's locating a + * feature. + * + * @param stack The stack to check. + * @return True if the stack is an empty FILLED_MAP awaiting to be populated with location data. + */ + @SuppressWarnings("DataFlowIssue") + public static boolean isEmptyPendingMap(ItemStack stack) { + return stack.getItem() == Items.FILLED_MAP && stack.hasTag() && stack.getTag().contains(KEY_LOCATING); + } + /** * Updates the map stack with all the given data. * @@ -44,7 +62,7 @@ public class CommonLogic { int scale, MapDecoration.Type destinationType ) { - updateMap(mapStack, level, pos, scale, destinationType, null); + updateMap(mapStack, level, pos, scale, destinationType, (Component)null); } /** @@ -64,6 +82,27 @@ public class CommonLogic { int scale, MapDecoration.Type destinationType, String displayName + ) { + updateMap(mapStack, level, pos, scale, destinationType, new TranslatableComponent(displayName)); + } + + /** + * Updates the map stack with all the given data. + * + * @param mapStack The map ItemStack to update + * @param level The ServerLevel + * @param pos The feature position + * @param scale The map scale + * @param destinationType The map feature type + * @param displayName The hover tooltip display name of the ItemStack + */ + public static void updateMap( + ItemStack mapStack, + ServerLevel level, + BlockPos pos, + int scale, + MapDecoration.Type destinationType, + Component displayName ) { MapItemAccess.callCreateAndStoreSavedData( mapStack, level, pos.getX(), pos.getZ(), scale, true, true, level.dimension() @@ -71,7 +110,8 @@ public class CommonLogic { MapItem.renderBiomePreviewMap(level, mapStack); MapItemSavedData.addTargetDecoration(mapStack, pos, "+", destinationType); if (displayName != null) - mapStack.setHoverName(new TranslatableComponent(displayName)); + mapStack.setHoverName(displayName); + mapStack.removeTagKey(KEY_LOCATING); } /** diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/structure/logic/ExplorationMapFunctionLogic.java b/forge/src/main/java/org/embeddedt/modernfix/forge/structure/logic/ExplorationMapFunctionLogic.java index 136c8b54..50fe7198 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/structure/logic/ExplorationMapFunctionLogic.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/structure/logic/ExplorationMapFunctionLogic.java @@ -1,7 +1,11 @@ package org.embeddedt.modernfix.forge.structure.logic; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import com.google.common.collect.ImmutableSet; import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -15,13 +19,29 @@ import net.minecraftforge.items.IItemHandlerModifiable; import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.forge.structure.AsyncLocator; +import java.util.Locale; +import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; // TODO: Need to test this public class ExplorationMapFunctionLogic { + // I'd like to think that structure locating shouldn't take *this* long + private static final Cache MAP_NAME_CACHE = + CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build(); + private static final int MAX_STACK_SIZE = 64; private ExplorationMapFunctionLogic() {} + public static void cacheName(ItemStack stack, Component name) { + MAP_NAME_CACHE.put(stack, name); + } + + public static Component getCachedName(ItemStack stack) { + Component name = MAP_NAME_CACHE.getIfPresent(stack); + MAP_NAME_CACHE.invalidate(stack); + return name; + } + public static void invalidateMap(ItemStack mapStack, ServerLevel level, BlockPos pos) { handleUpdateMapInChest(mapStack, level, pos, (handler, slot) -> { if (handler instanceof IItemHandlerModifiable) { @@ -39,9 +59,10 @@ public class ExplorationMapFunctionLogic { BlockPos pos, int scale, MapDecoration.Type destinationType, - BlockPos invPos + BlockPos invPos, + Component displayName ) { - CommonLogic.updateMap(mapStack, level, pos, scale, destinationType); + CommonLogic.updateMap(mapStack, level, pos, scale, destinationType, displayName); // Shouldn't need to set the stack in its slot again, as we're modifying the same instance handleUpdateMapInChest(mapStack, level, invPos, (handler, slot) -> {}); } @@ -84,12 +105,17 @@ public class ExplorationMapFunctionLogic { BlockPos pos, int scale, MapDecoration.Type destinationType, + StructureFeature destination, BlockPos invPos ) { if (pos == null) { invalidateMap(mapStack, level, invPos); } else { - updateMap(mapStack, level, pos, scale, destinationType, invPos); + Component displayName = getCachedName(mapStack); + if(displayName == null) { + displayName = new TranslatableComponent("filled_map." + destination.getFeatureName().toLowerCase(Locale.ROOT)); + } + updateMap(mapStack, level, pos, scale, destinationType, invPos, displayName); } } @@ -104,7 +130,7 @@ public class ExplorationMapFunctionLogic { ) { ItemStack mapStack = CommonLogic.createEmptyMap(); AsyncLocator.locateLevel(level, ImmutableSet.of(destination), blockPos, searchRadius, skipKnownStructures) - .thenOnServerThread(pos -> handleLocationFound(mapStack, level, pos, scale, destinationType, blockPos)); + .thenOnServerThread(pos -> handleLocationFound(mapStack, level, pos, scale, destinationType, destination, blockPos)); return mapStack; } } From 5de1518f767e6e0a114d40871da985ba8a028ae3 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 24 Sep 2023 11:53:39 -0400 Subject: [PATCH 11/11] Disable stronghold caching when C2ME is installed Related: #245 --- .../embeddedt/modernfix/core/config/ModernFixEarlyConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java index 67af3710..ecdf63a7 100644 --- a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java +++ b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java @@ -215,7 +215,7 @@ public class ModernFixEarlyConfig { disableIfModPresent("mixin.bugfix.remove_block_chunkloading", "performant"); disableIfModPresent("mixin.bugfix.paper_chunk_patches", "c2me"); disableIfModPresent("mixin.bugfix.preserve_early_window_pos", "better_loading_screen"); - disableIfModPresent("mixin.perf.cache_strongholds", "littletiles"); + disableIfModPresent("mixin.perf.cache_strongholds", "littletiles", "c2me"); // content overlap disableIfModPresent("mixin.perf.deduplicate_wall_shapes", "dashloader"); disableIfModPresent("mixin.perf.nbt_memory_usage", "c2me");