From 3ea6a0a3ed1ed857859346514047ea139cdac42c Mon Sep 17 00:00:00 2001 From: "yrsegal@gmail.com" Date: Sat, 30 Sep 2023 18:56:05 -0400 Subject: [PATCH] close #4356 --- .../vazkii/quark/base/handler/MiscUtil.java | 42 +++++++++++++++---- .../quark/base/module/ModuleLoader.java | 13 +++++- .../vazkii/quark/base/module/QuarkModule.java | 34 +++++++-------- .../vazkii/quark/base/proxy/ClientProxy.java | 12 ++++++ .../module/BucketsShowInhabitantsModule.java | 6 +-- .../tools/module/SkullPikesModule.java | 5 ++- .../tweaks/module/PatTheDogsModule.java | 5 ++- .../tweaks/module/PigLittersModule.java | 3 +- .../module/VillagersFollowEmeraldsModule.java | 5 ++- 9 files changed, 89 insertions(+), 36 deletions(-) diff --git a/src/main/java/vazkii/quark/base/handler/MiscUtil.java b/src/main/java/vazkii/quark/base/handler/MiscUtil.java index 17c5996a26..5b04dd716d 100644 --- a/src/main/java/vazkii/quark/base/handler/MiscUtil.java +++ b/src/main/java/vazkii/quark/base/handler/MiscUtil.java @@ -30,6 +30,9 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.MobSpawnType; +import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.entity.ai.goal.GoalSelector; +import net.minecraft.world.entity.ai.goal.WrappedGoal; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.enchantment.Enchantment; @@ -56,7 +59,6 @@ import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -import net.minecraftforge.fml.util.ObfuscationReflectionHelper; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemStackHandler; @@ -70,12 +72,7 @@ import vazkii.quark.mixin.accessor.AccessorLootTable; import javax.annotation.Nonnull; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.Random; +import java.util.*; import java.util.stream.Collectors; @EventBusSubscriber(modid = Quark.MOD_ID) @@ -105,6 +102,37 @@ public static BooleanProperty directionProperty(Direction direction) { }; } + /** + * Reconstructs the goal selector's list to add in a new goal. + * + * This is because vanilla doesn't play it safe around CMEs with skeletons. + * See: https://github.com/VazkiiMods/Quark/issues/4356 + * + * If a Skeleton is killed with Thorns damage and drops its weapon, it will reassess its goals. + * Because the thorns damage is being dealt during goal execution of the MeleeAttackGoal or RangedBowAttackGoal, + * this will cause a CME if the attack goal is not the VERY LAST goal in the set. + * + * Thankfully, the set GoalSelector uses is Linked, so we can just reconstruct the set and avoid the problem. + */ + public static void addGoalJustAfterLatestWithPriority(GoalSelector selector, int priority, Goal goal) { + Set allGoals = new LinkedHashSet<>(selector.getAvailableGoals()); + WrappedGoal latestWithPriority = null; + for (WrappedGoal wrappedGoal : allGoals) { + if (wrappedGoal.getPriority() == priority) + latestWithPriority = wrappedGoal; + } + + selector.removeAllGoals(); + if (latestWithPriority == null) + selector.addGoal(priority, goal); + + for (WrappedGoal wrappedGoal : allGoals) { + selector.addGoal(wrappedGoal.getPriority(), wrappedGoal.getGoal()); + if (wrappedGoal == latestWithPriority) + selector.addGoal(priority, goal); + } + } + @OnlyIn(Dist.CLIENT) public static void drawChatBubble(PoseStack matrix, int x, int y, Font font, String text, float alpha, boolean extendRight) { matrix.pushPose(); diff --git a/src/main/java/vazkii/quark/base/module/ModuleLoader.java b/src/main/java/vazkii/quark/base/module/ModuleLoader.java index 45d7d59af5..cfa53de361 100644 --- a/src/main/java/vazkii/quark/base/module/ModuleLoader.java +++ b/src/main/java/vazkii/quark/base/module/ModuleLoader.java @@ -33,7 +33,8 @@ public final class ModuleLoader { private enum Step { CONSTRUCT, CONSTRUCT_CLIENT, REGISTER, POST_REGISTER, CONFIG_CHANGED, CONFIG_CHANGED_CLIENT, SETUP, SETUP_CLIENT, REGISTER_RELOADABLE, MODEL_BAKE, MODEL_LAYERS, TEXTURE_STITCH, POST_TEXTURE_STITCH, LOAD_COMPLETE, GENERATE_HINTS, - FIRST_CLIENT_TICK, REGISTER_KEYBINDS, REGISTER_ADDITIONAL_MODELS, REGISTER_TOOLTIP_COMPONENT_FACTORIES + FIRST_CLIENT_TICK, REGISTER_KEYBINDS, REGISTER_ADDITIONAL_MODELS, REGISTER_TOOLTIP_COMPONENT_FACTORIES, + REGISTER_ITEM_COLORS, REGISTER_BLOCK_COLORS } public static final ModuleLoader INSTANCE = new ModuleLoader(); @@ -152,6 +153,16 @@ public void registerClientTooltipComponentFactories(RegisterClientTooltipCompone dispatch(Step.REGISTER_TOOLTIP_COMPONENT_FACTORIES, m -> m.registerClientTooltipComponentFactories(event)); } + @OnlyIn(Dist.CLIENT) + public void registerItemColors(RegisterColorHandlersEvent.Item event) { + dispatch(Step.REGISTER_ITEM_COLORS, m -> m.registerItemColors(event)); + } + + @OnlyIn(Dist.CLIENT) + public void registerBlockColors(RegisterColorHandlersEvent.Block event) { + dispatch(Step.REGISTER_BLOCK_COLORS, m -> m.registerBlockColors(event)); + } + public void loadComplete(ParallelDispatchEvent event) { this.event = event; dispatch(Step.LOAD_COMPLETE, QuarkModule::loadComplete); diff --git a/src/main/java/vazkii/quark/base/module/QuarkModule.java b/src/main/java/vazkii/quark/base/module/QuarkModule.java index 64b27a8e16..b1374381b1 100644 --- a/src/main/java/vazkii/quark/base/module/QuarkModule.java +++ b/src/main/java/vazkii/quark/base/module/QuarkModule.java @@ -1,35 +1,25 @@ package vazkii.quark.base.module; -import java.util.List; -import java.util.Optional; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Supplier; - import com.google.common.collect.Lists; - -import net.minecraft.core.Registry; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.PreparableReloadListener; import net.minecraft.world.item.Item; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.client.event.EntityRenderersEvent; -import net.minecraftforge.client.event.ModelEvent; -import net.minecraftforge.client.event.RegisterClientTooltipComponentFactoriesEvent; -import net.minecraftforge.client.event.RegisterKeyMappingsEvent; -import net.minecraftforge.client.event.TextureStitchEvent; +import net.minecraftforge.client.event.*; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.loading.FMLEnvironment; -import vazkii.arl.util.RegistryHelper; import vazkii.quark.api.event.ModuleLoadedEvent; import vazkii.quark.api.event.ModuleStateChangedEvent; import vazkii.quark.base.Quark; import vazkii.quark.base.module.config.ConfigFlagManager; import vazkii.quark.base.module.hint.HintObject; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + public class QuarkModule { public ModuleCategory category = null; @@ -127,6 +117,16 @@ public void registerAdditionalModels(ModelEvent.RegisterAdditional event) { // NO-OP } + @OnlyIn(Dist.CLIENT) + public void registerItemColors(RegisterColorHandlersEvent.Item event) { + // NO-OP + } + + @OnlyIn(Dist.CLIENT) + public void registerBlockColors(RegisterColorHandlersEvent.Block event) { + // NO-OP + } + @OnlyIn(Dist.CLIENT) public void registerClientTooltipComponentFactories(RegisterClientTooltipComponentFactoriesEvent event) { // NO-OP @@ -139,7 +139,7 @@ public void loadComplete() { public final void addStackInfo(BiConsumer consumer) { if(!enabled) return; - + for(HintObject hint : hints) hint.apply(consumer); addAdditionalHints(consumer); @@ -147,7 +147,7 @@ public final void addStackInfo(BiConsumer consumer) { public void addAdditionalHints(BiConsumer consumer) { - } + } @OnlyIn(Dist.CLIENT) public void firstClientTick() { diff --git a/src/main/java/vazkii/quark/base/proxy/ClientProxy.java b/src/main/java/vazkii/quark/base/proxy/ClientProxy.java index 15071443f2..abbd8caf9b 100644 --- a/src/main/java/vazkii/quark/base/proxy/ClientProxy.java +++ b/src/main/java/vazkii/quark/base/proxy/ClientProxy.java @@ -72,6 +72,8 @@ public void registerListeners(IEventBus bus) { bus.addListener(this::registerKeybinds); bus.addListener(this::registerAdditionalModels); bus.addListener(this::registerClientTooltipComponentFactories); + bus.addListener(this::registerItemColors); + bus.addListener(this::registerBlockColors); } public void clientSetup(FMLClientSetupEvent event) { @@ -115,6 +117,16 @@ public void registerClientTooltipComponentFactories(RegisterClientTooltipCompone ModuleLoader.INSTANCE.registerClientTooltipComponentFactories(event); } + @OnlyIn(Dist.CLIENT) + public void registerItemColors(RegisterColorHandlersEvent.Item event) { + ModuleLoader.INSTANCE.registerItemColors(event); + } + + @OnlyIn(Dist.CLIENT) + public void registerBlockColors(RegisterColorHandlersEvent.Block event) { + ModuleLoader.INSTANCE.registerBlockColors(event); + } + @Override public void handleQuarkConfigChange() { super.handleQuarkConfigChange(); diff --git a/src/main/java/vazkii/quark/content/client/module/BucketsShowInhabitantsModule.java b/src/main/java/vazkii/quark/content/client/module/BucketsShowInhabitantsModule.java index 3c18c89482..a1afc90b26 100644 --- a/src/main/java/vazkii/quark/content/client/module/BucketsShowInhabitantsModule.java +++ b/src/main/java/vazkii/quark/content/client/module/BucketsShowInhabitantsModule.java @@ -18,8 +18,6 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.event.RegisterColorHandlersEvent; -import net.minecraftforge.eventbus.api.EventPriority; -import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.registries.ForgeRegistries; import vazkii.arl.util.ItemNBTHelper; import vazkii.quark.base.Quark; @@ -39,7 +37,7 @@ import java.util.function.BooleanSupplier; import java.util.function.IntUnaryOperator; -@LoadModule(category = ModuleCategory.CLIENT, subscribeOn = Dist.CLIENT) +@LoadModule(category = ModuleCategory.CLIENT) public class BucketsShowInhabitantsModule extends QuarkModule { @Config @@ -70,8 +68,8 @@ public void clientSetup() { }); } + @Override @OnlyIn(Dist.CLIENT) - @SubscribeEvent(priority = EventPriority.LOWEST) public void registerItemColors(RegisterColorHandlersEvent.Item evt) { Holder.Reference tropicalBucket = ForgeRegistries.ITEMS.getDelegateOrThrow(Items.TROPICAL_FISH_BUCKET); ItemColor parent = ((AccessorItemColors) evt.getItemColors()).quark$getItemColors().get(tropicalBucket); diff --git a/src/main/java/vazkii/quark/content/tools/module/SkullPikesModule.java b/src/main/java/vazkii/quark/content/tools/module/SkullPikesModule.java index c4b261dfc0..0f747bcac5 100644 --- a/src/main/java/vazkii/quark/content/tools/module/SkullPikesModule.java +++ b/src/main/java/vazkii/quark/content/tools/module/SkullPikesModule.java @@ -22,6 +22,7 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import vazkii.arl.util.RegistryHelper; import vazkii.quark.base.Quark; +import vazkii.quark.base.handler.MiscUtil; import vazkii.quark.base.module.LoadModule; import vazkii.quark.base.module.ModuleCategory; import vazkii.quark.base.module.QuarkModule; @@ -36,7 +37,7 @@ public class SkullPikesModule extends QuarkModule { public static EntityType skullPikeType; - @Hint(key = "skull_pikes") + @Hint(key = "skull_pikes") public static TagKey pikeTrophiesTag; @Config public static double pikeRange = 5; @@ -92,7 +93,7 @@ public void onMonsterAppear(EntityJoinLevelEvent event) { boolean alreadySetUp = monster.goalSelector.getAvailableGoals().stream().anyMatch((goal) -> goal.getGoal() instanceof RunAwayFromPikesGoal); if (!alreadySetUp) - monster.goalSelector.addGoal(3, new RunAwayFromPikesGoal(monster, (float) pikeRange, 1.0D, 1.2D)); + MiscUtil.addGoalJustAfterLatestWithPriority(monster.goalSelector, 3, new RunAwayFromPikesGoal(monster, (float) pikeRange, 1.0D, 1.2D)); } } } diff --git a/src/main/java/vazkii/quark/content/tweaks/module/PatTheDogsModule.java b/src/main/java/vazkii/quark/content/tweaks/module/PatTheDogsModule.java index 87ac13f442..eae14c962e 100644 --- a/src/main/java/vazkii/quark/content/tweaks/module/PatTheDogsModule.java +++ b/src/main/java/vazkii/quark/content/tweaks/module/PatTheDogsModule.java @@ -18,6 +18,7 @@ import net.minecraftforge.event.entity.living.AnimalTameEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; +import vazkii.quark.base.handler.MiscUtil; import vazkii.quark.base.handler.QuarkSounds; import vazkii.quark.base.module.LoadModule; import vazkii.quark.base.module.ModuleCategory; @@ -50,8 +51,8 @@ public void onWolfAppear(EntityJoinLevelEvent event) { boolean alreadySetUp = wolf.goalSelector.getAvailableGoals().stream().anyMatch((goal) -> goal.getGoal() instanceof WantLoveGoal); if (!alreadySetUp) { - wolf.goalSelector.addGoal(4, new NuzzleGoal(wolf, 0.5F, 16, 2, SoundEvents.WOLF_WHINE)); - wolf.goalSelector.addGoal(5, new WantLoveGoal(wolf, 0.2F)); + MiscUtil.addGoalJustAfterLatestWithPriority(wolf.goalSelector, 4, new NuzzleGoal(wolf, 0.5F, 16, 2, SoundEvents.WOLF_WHINE)); + MiscUtil.addGoalJustAfterLatestWithPriority(wolf.goalSelector, 5, new WantLoveGoal(wolf, 0.2F)); } } } diff --git a/src/main/java/vazkii/quark/content/tweaks/module/PigLittersModule.java b/src/main/java/vazkii/quark/content/tweaks/module/PigLittersModule.java index 7402bf2ecf..3ad7bc8d64 100644 --- a/src/main/java/vazkii/quark/content/tweaks/module/PigLittersModule.java +++ b/src/main/java/vazkii/quark/content/tweaks/module/PigLittersModule.java @@ -22,6 +22,7 @@ import net.minecraftforge.event.entity.living.LivingEvent; import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; +import vazkii.quark.base.handler.MiscUtil; import vazkii.quark.base.module.LoadModule; import vazkii.quark.base.module.ModuleCategory; import vazkii.quark.base.module.ModuleLoader; @@ -80,7 +81,7 @@ public void onPigAppear(EntityJoinLevelEvent event) { .orElse(-1); if (priority >= 0) - pig.goalSelector.addGoal(4, new TemptGoal(pig, 1.2D, Ingredient.of(Items.GOLDEN_CARROT), false)); + MiscUtil.addGoalJustAfterLatestWithPriority(pig.goalSelector, 4, new TemptGoal(pig, 1.2D, Ingredient.of(Items.GOLDEN_CARROT), false)); } } } diff --git a/src/main/java/vazkii/quark/content/tweaks/module/VillagersFollowEmeraldsModule.java b/src/main/java/vazkii/quark/content/tweaks/module/VillagersFollowEmeraldsModule.java index f3ae523762..dfd0beac23 100644 --- a/src/main/java/vazkii/quark/content/tweaks/module/VillagersFollowEmeraldsModule.java +++ b/src/main/java/vazkii/quark/content/tweaks/module/VillagersFollowEmeraldsModule.java @@ -7,6 +7,7 @@ import net.minecraft.world.item.crafting.Ingredient; import net.minecraftforge.event.entity.EntityJoinLevelEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; +import vazkii.quark.base.handler.MiscUtil; import vazkii.quark.base.module.LoadModule; import vazkii.quark.base.module.ModuleCategory; import vazkii.quark.base.module.QuarkModule; @@ -18,7 +19,7 @@ */ @LoadModule(category = ModuleCategory.TWEAKS, hasSubscriptions = true) public class VillagersFollowEmeraldsModule extends QuarkModule { - + @Hint Item emerald_block = Items.EMERALD_BLOCK; @SubscribeEvent @@ -28,7 +29,7 @@ public void onVillagerAppear(EntityJoinLevelEvent event) { if (!alreadySetUp) try { - villager.goalSelector.addGoal(2, new TemptGoal(villager, 0.6, Ingredient.of(Items.EMERALD_BLOCK), false)); + MiscUtil.addGoalJustAfterLatestWithPriority(villager.goalSelector, 2, new TemptGoal(villager, 0.6, Ingredient.of(Items.EMERALD_BLOCK), false)); } catch(IllegalArgumentException e) { // This appears to be a weird bug that happens when a villager is riding something and its chunk unloads }