From 9b9b13d24b450116bc4325e8b5b2e3f4498f52ff Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 19 Feb 2023 22:19:20 -0500 Subject: [PATCH] Add KubeJS optimizations --- build.gradle | 17 ++++ gradle.properties | 3 +- .../core/config/ModernFixEarlyConfig.java | 1 + .../perf/kubejs/TagIngredientJSMixin.java | 28 +++++++ .../mixin/perf/kubejs/TagWrapperMixin.java | 82 +++++++++++++++++++ .../embeddedt/modernfix/util/KubeUtil.java | 20 +++++ src/main/resources/modernfix.mixins.json | 4 +- 7 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/embeddedt/modernfix/mixin/perf/kubejs/TagIngredientJSMixin.java create mode 100644 src/main/java/org/embeddedt/modernfix/mixin/perf/kubejs/TagWrapperMixin.java create mode 100644 src/main/java/org/embeddedt/modernfix/util/KubeUtil.java diff --git a/build.gradle b/build.gradle index 86ef5518..cc0a8c08 100644 --- a/build.gradle +++ b/build.gradle @@ -43,6 +43,21 @@ repositories { name = 'ParchmentMC' url = 'https://maven.parchmentmc.org' } + maven { + // Shedaniel's maven (Architectury API) + url = "https://maven.architectury.dev" + content { + includeGroup "me.shedaniel" + } + } + + maven { + // saps.dev Maven (KubeJS and Rhino) + url = "https://maven.saps.dev/minecraft" + content { + includeGroup "dev.latvian.mods" + } + } } dependencies { @@ -70,6 +85,8 @@ dependencies { modRuntimeOnly("mezz.jei:jei-${minecraft_version}:${jei_version}") modCompileOnly("curse.maven:refinedstorage-243076:${refined_storage_version}") + + modImplementation("dev.latvian.mods:kubejs-forge:${kubejs_version}") } tasks.withType(JavaCompile) { diff --git a/gradle.properties b/gradle.properties index 2dcde3cd..6361e3d5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,4 +14,5 @@ lazydfu_version=3249059 mekanism_version=1.16.5-10.1.2.457 parchment_version=2022.03.06 jei_version=7.7.1.153 -refined_storage_version=3807951 \ No newline at end of file +refined_storage_version=3807951 +kubejs_version=1605.3.19-build.299 \ No newline at end of file diff --git a/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java b/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java index d4c8e106..7add26e8 100644 --- a/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java +++ b/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java @@ -44,6 +44,7 @@ public class ModernFixEarlyConfig { this.addMixinRule("perf.cache_model_materials", true); this.addMixinRule("perf.datapack_reload_exceptions", true); this.addMixinRule("perf.async_locator", true); + this.addMixinRule("perf.kubejs", true); /* Keep this off if JEI isn't installed to prevent breaking vanilla gameplay */ this.addMixinRule("perf.blast_search_trees", FMLLoader.getLoadingModList().getModFileById("jei") != null); this.addMixinRule("safety", true); diff --git a/src/main/java/org/embeddedt/modernfix/mixin/perf/kubejs/TagIngredientJSMixin.java b/src/main/java/org/embeddedt/modernfix/mixin/perf/kubejs/TagIngredientJSMixin.java new file mode 100644 index 00000000..080ef036 --- /dev/null +++ b/src/main/java/org/embeddedt/modernfix/mixin/perf/kubejs/TagIngredientJSMixin.java @@ -0,0 +1,28 @@ +package org.embeddedt.modernfix.mixin.perf.kubejs; + +import dev.latvian.kubejs.item.ItemStackJS; +import dev.latvian.kubejs.item.ingredient.IngredientJS; +import dev.latvian.kubejs.item.ingredient.TagIngredientJS; +import net.minecraft.tags.Tag; +import net.minecraft.world.item.Item; +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(TagIngredientJS.class) +public abstract class TagIngredientJSMixin { + @Shadow public abstract Tag getActualTag(); + + /** + * @author embeddedt + * @reason avoid pointless construction of many ItemStack objects + */ + @Inject(method = "anyStackMatches", at = @At("HEAD"), cancellable = true, remap = false) + private void checkItemOnly(IngredientJS ingredient, CallbackInfoReturnable cir) { + if(ingredient instanceof ItemStackJS) { + cir.setReturnValue(((ItemStackJS)ingredient).getItem().is(this.getActualTag())); + } + } +} diff --git a/src/main/java/org/embeddedt/modernfix/mixin/perf/kubejs/TagWrapperMixin.java b/src/main/java/org/embeddedt/modernfix/mixin/perf/kubejs/TagWrapperMixin.java new file mode 100644 index 00000000..aea5eb05 --- /dev/null +++ b/src/main/java/org/embeddedt/modernfix/mixin/perf/kubejs/TagWrapperMixin.java @@ -0,0 +1,82 @@ +package org.embeddedt.modernfix.mixin.perf.kubejs; + +import dev.latvian.kubejs.server.TagEventJS; +import dev.latvian.kubejs.util.ConsoleJS; +import dev.latvian.kubejs.util.ListJS; +import dev.latvian.kubejs.util.UtilsJS; +import it.unimi.dsi.fastutil.chars.CharOpenHashSet; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import me.shedaniel.architectury.registry.Registry; +import net.minecraft.resources.ResourceLocation; +import org.embeddedt.modernfix.util.KubeUtil; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +@Mixin(TagEventJS.TagWrapper.class) +public class TagWrapperMixin { + private static final CharOpenHashSet REGEX_SPECIAL_CHARS = new CharOpenHashSet(new char[] { + '.', '+', '*','?','^','$','(',')','[',']','{','}','|','\\', '/' + }); + + /** + * @author embeddedt + * @reason only iterate over the whole registry if a regex is given, otherwise use the given registry name as-is + */ + @Redirect(method = "add", at = @At(value = "INVOKE", target = "Ldev/latvian/kubejs/util/UtilsJS;parseRegex(Ljava/lang/Object;)Ljava/util/regex/Pattern;"), remap = false) + private Pattern skipRegex(Object o) { + String inputStr = (String)o; + boolean regexCharFound = false; + for(int i = 0; i < inputStr.length(); i++) { + if(REGEX_SPECIAL_CHARS.contains(inputStr.charAt(i))) { + System.out.println(inputStr); + regexCharFound = true; + break; + } + } + if(regexCharFound) + return UtilsJS.parseRegex(inputStr); + else + return null; + } + + private String currentPatternStr = null; + @Inject(method = "add", at = @At(value = "INVOKE", target = "Lme/shedaniel/architectury/registry/Registry;getIds()Ljava/util/Set;", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD, remap = false) + private void saveCurrentPattern(Object ids, CallbackInfoReturnable> cir, Iterator iterator, Object o, String patternStr) { + currentPatternStr = patternStr; + } + + @Redirect(method = "add", at = @At(value = "INVOKE", target = "Lme/shedaniel/architectury/registry/Registry;getIds()Ljava/util/Set;", ordinal = 0), remap = false) + private Set getCachedIds(Registry registryIn) { + if(currentPatternStr == null) + throw new AssertionError(); + Set cachedSet = KubeUtil.matchedIdsForRegex.get(currentPatternStr); + if(cachedSet == null) { + Pattern thePattern = UtilsJS.parseRegex(currentPatternStr); + ArrayList locations = new ArrayList<>(registryIn.getIds()); + cachedSet = locations.parallelStream() + .filter(rLoc -> thePattern.matcher(rLoc.toString()).find()) + .collect(Collectors.toSet()); + KubeUtil.matchedIdsForRegex.put(currentPatternStr, cachedSet); + } + return cachedSet; + } + + /** + * @author embeddedt + * @reason we handle pattern-matching ourselves to build the cache + */ + @Redirect(method = "add", at = @At(value = "INVOKE", target = "Ljava/util/regex/Matcher;find()Z"), remap = false) + private boolean isMatchedStr(Matcher matcher) { + return true; + } +} diff --git a/src/main/java/org/embeddedt/modernfix/util/KubeUtil.java b/src/main/java/org/embeddedt/modernfix/util/KubeUtil.java new file mode 100644 index 00000000..1f453d47 --- /dev/null +++ b/src/main/java/org/embeddedt/modernfix/util/KubeUtil.java @@ -0,0 +1,20 @@ +package org.embeddedt.modernfix.util; + +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.event.AddReloadListenerEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import org.embeddedt.modernfix.ModernFix; + +import java.util.HashMap; +import java.util.Set; + +@Mod.EventBusSubscriber(modid = ModernFix.MODID) +public class KubeUtil { + public static final HashMap> matchedIdsForRegex = new HashMap<>(); + + @SubscribeEvent + public static void clearRegexCache(AddReloadListenerEvent event) { + matchedIdsForRegex.clear(); + } +} diff --git a/src/main/resources/modernfix.mixins.json b/src/main/resources/modernfix.mixins.json index 59a193dd..f0df6b32 100644 --- a/src/main/resources/modernfix.mixins.json +++ b/src/main/resources/modernfix.mixins.json @@ -41,7 +41,9 @@ "perf.async_locator.TreasureMapForEmeraldsMixin", "feature.measure_time.BootstrapMixin", "feature.measure_time.SimpleReloadableResourceManagerMixin", - "feature.measure_time.ProfiledReloadInstanceMixin" + "feature.measure_time.ProfiledReloadInstanceMixin", + "perf.kubejs.TagIngredientJSMixin", + "perf.kubejs.TagWrapperMixin" ], "client": [ "feature.measure_time.MinecraftMixin",