From 4c2ccc043ead09933b84239b900c4673585b8871 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 18 Feb 2022 17:43:12 +0100 Subject: [PATCH 1/5] [ci skip] Some cleanup for Platform class and other platform-specific stuff (#201) * Ensure paths returned by Platform are absolute, add javadocs to Platform Signed-off-by: Max * Use putIfAbsent for event buses to clean up some minor nastyness Signed-off-by: Max * Remove explicit NotNull annotation --- .../dev/architectury/platform/Platform.java | 68 ++++++++++++++++++- .../platform/fabric/PlatformImpl.java | 6 +- .../platform/forge/EventBuses.java | 4 +- .../platform/forge/PlatformImpl.java | 4 +- 4 files changed, 73 insertions(+), 9 deletions(-) diff --git a/common/src/main/java/dev/architectury/platform/Platform.java b/common/src/main/java/dev/architectury/platform/Platform.java index b78edd8a..5f813b59 100644 --- a/common/src/main/java/dev/architectury/platform/Platform.java +++ b/common/src/main/java/dev/architectury/platform/Platform.java @@ -24,9 +24,11 @@ import dev.architectury.injectables.targets.ArchitecturyTarget; import dev.architectury.utils.Env; import net.fabricmc.api.EnvType; import net.minecraft.SharedConstants; +import org.jetbrains.annotations.NotNull; import java.nio.file.Path; import java.util.Collection; +import java.util.NoSuchElementException; import java.util.Optional; public final class Platform { @@ -60,54 +62,118 @@ public final class Platform { return SharedConstants.getCurrentVersion().getId(); } + /** + * Gets the root directory for the current instance of Minecraft. + *

+ * The returned path is guaranteed to be absolute. + */ @ExpectPlatform public static Path getGameFolder() { throw new AssertionError(); } + /** + * Gets the main config folder for the current instance of Minecraft. + *

+ * The returned path is guaranteed to be absolute. + */ @ExpectPlatform public static Path getConfigFolder() { throw new AssertionError(); } + /** + * Gets the mods folder of the current instance of Minecraft. + *

+ * The returned path is guaranteed to be absolute. + */ @ExpectPlatform public static Path getModsFolder() { throw new AssertionError(); } + /** + * Returns the current Environment the game is running in, + * being one of either CLIENT or SERVER. + *

+ * The class returned is a platform-agnostic wrapper around the + * EnvType and Dist enums, respectively. + * + * @return The current Environment, as an instance of {@link Env} + * @see Env + * @see #getEnv() + */ @ExpectPlatform public static Env getEnvironment() { throw new AssertionError(); } + /** + * Returns the current Environment the game is running in, + * as a member of the {@link EnvType} enum. This is remapped + * on Forge to be the Dist enum, instead. + * + * @return The current Environment, as an instance of {@link EnvType} + * (or Dist on Forge) + */ @ExpectPlatform public static EnvType getEnv() { throw new AssertionError(); } + /** + * Checks whether a mod with the given mod ID is present. + * + * @param id The mod ID to check. + * @return true if the mod is loaded, false otherwise. + */ @ExpectPlatform public static boolean isModLoaded(String id) { throw new AssertionError(); } + /** + * Gets a {@link Mod} container by its mod ID. + * + * @param id The mod ID to look for. + * @return The mod container, if found. + * @throws NoSuchElementException if no mod with the given ID exists + */ @ExpectPlatform public static Mod getMod(String id) { throw new AssertionError(); } + /** + * Optionally gets a {@link Mod} container by its mod ID if it exists. + * + * @param id The mod ID to look for. + * @return An optional representing the mod container, if found, + * or an empty optional otherwise. + */ public static Optional getOptionalMod(String id) { try { return Optional.of(getMod(id)); - } catch (NullPointerException e) { + } catch (NoSuchElementException e) { return Optional.empty(); } } + /** + * Gets a collection of {@link Mod} containers for all currently-loaded mods. + * + * @return A collection of mod containers. + */ @ExpectPlatform public static Collection getMods() { throw new AssertionError(); } + /** + * Gets a collection of Strings representing the mod IDs of all currently-loaded mods. + * + * @return A collection of all loaded mod IDs. + */ @ExpectPlatform public static Collection getModIds() { throw new AssertionError(); diff --git a/fabric/src/main/java/dev/architectury/platform/fabric/PlatformImpl.java b/fabric/src/main/java/dev/architectury/platform/fabric/PlatformImpl.java index 12053ccd..e91e608c 100644 --- a/fabric/src/main/java/dev/architectury/platform/fabric/PlatformImpl.java +++ b/fabric/src/main/java/dev/architectury/platform/fabric/PlatformImpl.java @@ -41,11 +41,11 @@ public class PlatformImpl { private static final Map mods = new ConcurrentHashMap<>(); public static Path getGameFolder() { - return FabricLoader.getInstance().getGameDir(); + return FabricLoader.getInstance().getGameDir().toAbsolutePath(); } public static Path getConfigFolder() { - return FabricLoader.getInstance().getConfigDir(); + return FabricLoader.getInstance().getConfigDir().toAbsolutePath(); } public static Path getModsFolder() { @@ -88,7 +88,7 @@ public class PlatformImpl { private final ModMetadata metadata; public ModImpl(String id) { - this.container = FabricLoader.getInstance().getModContainer(id).get(); + this.container = FabricLoader.getInstance().getModContainer(id).orElseThrow(); this.metadata = this.container.getMetadata(); } diff --git a/forge/src/main/java/dev/architectury/platform/forge/EventBuses.java b/forge/src/main/java/dev/architectury/platform/forge/EventBuses.java index 05d0e11d..a37b694b 100644 --- a/forge/src/main/java/dev/architectury/platform/forge/EventBuses.java +++ b/forge/src/main/java/dev/architectury/platform/forge/EventBuses.java @@ -32,9 +32,7 @@ public final class EventBuses { private static final Map>> ON_REGISTERED = new HashMap<>(); public static void registerModEventBus(String modId, IEventBus bus) { - IEventBus previous = EVENT_BUS_MAP.put(modId, bus); - if (previous != null) { - EVENT_BUS_MAP.put(modId, previous); + if (EVENT_BUS_MAP.putIfAbsent(modId, bus) != bus) { throw new IllegalStateException("Can't register event bus for mod '" + modId + "' because it was previously registered!"); } diff --git a/forge/src/main/java/dev/architectury/platform/forge/PlatformImpl.java b/forge/src/main/java/dev/architectury/platform/forge/PlatformImpl.java index cf79daf3..a281e39f 100644 --- a/forge/src/main/java/dev/architectury/platform/forge/PlatformImpl.java +++ b/forge/src/main/java/dev/architectury/platform/forge/PlatformImpl.java @@ -92,11 +92,11 @@ public class PlatformImpl { private final IModInfo info; public ModImpl(String id) { - this.container = ModList.get().getModContainerById(id).get(); + this.container = ModList.get().getModContainerById(id).orElseThrow(); this.info = ModList.get().getMods().stream() .filter(modInfo -> Objects.equals(modInfo.getModId(), id)) .findAny() - .get(); + .orElseThrow(); } @Override From 397e5c7a6af79e3a8617fb4fabab1fb390f04147 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Sat, 19 Feb 2022 00:43:22 +0800 Subject: [PATCH 2/5] [ci skip] Requires Fabric Loader 0.13.0 (#194) --- .../fabric/client/MixinGameRenderer.java | 10 ++- .../fabric/client/MixinGameRenderer013.java | 73 ------------------- .../fabric/ArchitecturyMixinPlugin.java | 21 +----- .../main/resources/architectury.mixins.json | 1 - fabric/src/main/resources/fabric.mod.json | 2 +- 5 files changed, 8 insertions(+), 99 deletions(-) delete mode 100644 fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinGameRenderer013.java diff --git a/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinGameRenderer.java b/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinGameRenderer.java index 4926b7b0..8dab3598 100644 --- a/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinGameRenderer.java +++ b/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinGameRenderer.java @@ -19,9 +19,11 @@ package dev.architectury.mixin.fabric.client; +import com.mojang.blaze3d.platform.Window; import com.mojang.blaze3d.shaders.Program; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.datafixers.util.Pair; +import com.mojang.math.Matrix4f; import dev.architectury.event.events.client.ClientGuiEvent; import dev.architectury.event.events.client.ClientReloadShadersEvent; import net.minecraft.client.Minecraft; @@ -48,8 +50,8 @@ public abstract class MixinGameRenderer { @Inject(method = "render(FJZ)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;render(Lcom/mojang/blaze3d/vertex/PoseStack;IIF)V", ordinal = 0), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true) - public void renderScreenPre(float tickDelta, long startTime, boolean tick, CallbackInfo ci, int mouseX, int mouseY, PoseStack matrices) { - if (ClientGuiEvent.RENDER_PRE.invoker().render(minecraft.screen, matrices, mouseX, mouseY, minecraft.getDeltaFrameTime()).isFalse()) { + public void renderScreenPre(float tickDelta, long startTime, boolean tick, CallbackInfo ci, int mouseX, int mouseY, Window window, Matrix4f matrix, PoseStack matrices, PoseStack matrices2) { + if (ClientGuiEvent.RENDER_PRE.invoker().render(minecraft.screen, matrices2, mouseX, mouseY, minecraft.getDeltaFrameTime()).isFalse()) { ci.cancel(); } } @@ -57,8 +59,8 @@ public abstract class MixinGameRenderer { @Inject(method = "render(FJZ)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;render(Lcom/mojang/blaze3d/vertex/PoseStack;IIF)V", shift = At.Shift.AFTER, ordinal = 0), locals = LocalCapture.CAPTURE_FAILEXCEPTION) - public void renderScreenPost(float tickDelta, long startTime, boolean tick, CallbackInfo ci, int mouseX, int mouseY, PoseStack matrices) { - ClientGuiEvent.RENDER_POST.invoker().render(minecraft.screen, matrices, mouseX, mouseY, minecraft.getDeltaFrameTime()); + public void renderScreenPost(float tickDelta, long startTime, boolean tick, CallbackInfo ci, int mouseX, int mouseY, Window window, Matrix4f matrix, PoseStack matrices, PoseStack matrices2) { + ClientGuiEvent.RENDER_POST.invoker().render(minecraft.screen, matrices2, mouseX, mouseY, minecraft.getDeltaFrameTime()); } @Inject(method = "reloadShaders", diff --git a/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinGameRenderer013.java b/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinGameRenderer013.java deleted file mode 100644 index dde7d326..00000000 --- a/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinGameRenderer013.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * This file is part of architectury. - * Copyright (C) 2020, 2021, 2022 architectury - * - * This program 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; either - * version 3 of the License, or (at your option) any later version. - * - * This program 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 program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -package dev.architectury.mixin.fabric.client; - -import com.mojang.blaze3d.platform.Window; -import com.mojang.blaze3d.shaders.Program; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.datafixers.util.Pair; -import com.mojang.math.Matrix4f; -import dev.architectury.event.events.client.ClientGuiEvent; -import dev.architectury.event.events.client.ClientReloadShadersEvent; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.ShaderInstance; -import net.minecraft.server.packs.resources.ResourceManager; -import org.spongepowered.asm.mixin.Final; -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.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import java.util.List; -import java.util.function.Consumer; - -@Mixin(value = GameRenderer.class, priority = 1100) -public abstract class MixinGameRenderer013 { - @Shadow - @Final - private Minecraft minecraft; - - @Inject(method = "render(FJZ)V", - at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;render(Lcom/mojang/blaze3d/vertex/PoseStack;IIF)V", - ordinal = 0), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true) - public void renderScreenPre(float tickDelta, long startTime, boolean tick, CallbackInfo ci, int mouseX, int mouseY, Window window, Matrix4f matrix, PoseStack matrices, PoseStack matrices2) { - if (ClientGuiEvent.RENDER_PRE.invoker().render(minecraft.screen, matrices2, mouseX, mouseY, minecraft.getDeltaFrameTime()).isFalse()) { - ci.cancel(); - } - } - - @Inject(method = "render(FJZ)V", - at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;render(Lcom/mojang/blaze3d/vertex/PoseStack;IIF)V", - shift = At.Shift.AFTER, ordinal = 0), locals = LocalCapture.CAPTURE_FAILEXCEPTION) - public void renderScreenPost(float tickDelta, long startTime, boolean tick, CallbackInfo ci, int mouseX, int mouseY, Window window, Matrix4f matrix, PoseStack matrices, PoseStack matrices2) { - ClientGuiEvent.RENDER_POST.invoker().render(minecraft.screen, matrices2, mouseX, mouseY, minecraft.getDeltaFrameTime()); - } - - @Inject(method = "reloadShaders", - at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 0), locals = LocalCapture.CAPTURE_FAILEXCEPTION) - public void reloadShaders(ResourceManager resourceManager, CallbackInfo ci, List programs, List>> shaders) { - ClientReloadShadersEvent.EVENT.invoker().reload(resourceManager, (shader, callback) -> { - shaders.add(Pair.of(shader, callback)); - }); - } -} \ No newline at end of file diff --git a/fabric/src/main/java/dev/architectury/plugin/fabric/ArchitecturyMixinPlugin.java b/fabric/src/main/java/dev/architectury/plugin/fabric/ArchitecturyMixinPlugin.java index a4bdf3d7..46e486d2 100644 --- a/fabric/src/main/java/dev/architectury/plugin/fabric/ArchitecturyMixinPlugin.java +++ b/fabric/src/main/java/dev/architectury/plugin/fabric/ArchitecturyMixinPlugin.java @@ -19,7 +19,7 @@ package dev.architectury.plugin.fabric; -import net.fabricmc.loader.api.*; +import net.fabricmc.loader.api.FabricLoader; import org.objectweb.asm.tree.ClassNode; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; @@ -38,29 +38,10 @@ public class ArchitecturyMixinPlugin implements IMixinConfigPlugin { return null; } - private boolean isLoader013() { - ModContainer fabricLoader = FabricLoader.getInstance().getModContainer("fabricloader") - .orElseThrow(() -> new IllegalStateException("Where is fabricloader?")); - Version version = fabricLoader.getMetadata().getVersion(); - if (version instanceof SemanticVersion) { - try { - return version.compareTo(SemanticVersion.parse("0.13-")) >= 0; - } catch (VersionParsingException e) { - throw new IllegalStateException("Failed to parse version", e); - } - } - System.err.println("FabricLoader is not a SemanticVersion, cannot determine if it is >= 0.13"); - return true; - } - @Override public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { if ("dev.architectury.mixin.fabric.client.MixinEffectInstance".equals(mixinClassName)) { return !FabricLoader.getInstance().isModLoaded("satin"); - } else if ("dev.architectury.mixin.fabric.client.MixinGameRenderer".equals(mixinClassName)) { - return !isLoader013(); - } else if ("dev.architectury.mixin.fabric.client.MixinGameRenderer013".equals(mixinClassName)) { - return isLoader013(); } return true; } diff --git a/fabric/src/main/resources/architectury.mixins.json b/fabric/src/main/resources/architectury.mixins.json index fcad6648..f036e515 100644 --- a/fabric/src/main/resources/architectury.mixins.json +++ b/fabric/src/main/resources/architectury.mixins.json @@ -10,7 +10,6 @@ "client.MixinDebugScreenOverlay", "client.MixinEffectInstance", "client.MixinGameRenderer", - "client.MixinGameRenderer013", "client.MixinIntegratedServer", "client.MixinKeyboardHandler", "client.MixinMinecraft", diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index 04fb186c..875fe0ae 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -36,7 +36,7 @@ "icon": "icon.png", "depends": { "minecraft": "~1.18-", - "fabricloader": ">=0.12.0", + "fabricloader": ">=0.13.0", "fabric": ">=0.44.0" }, "custom": { From 60b21d2364407fdb2924807933c34c1bf58a6230 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Sat, 19 Feb 2022 00:43:32 +0800 Subject: [PATCH 3/5] [ci skip] Allow registering entries after it has been collected on Forge (#193) * Allow registering entries after it has been collected on Forge * Fix compilation --- .../registries/forge/RegistriesImpl.java | 42 +++++++++++++------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/forge/src/main/java/dev/architectury/registry/registries/forge/RegistriesImpl.java b/forge/src/main/java/dev/architectury/registry/registries/forge/RegistriesImpl.java index 98795641..68c8a9bb 100644 --- a/forge/src/main/java/dev/architectury/registry/registries/forge/RegistriesImpl.java +++ b/forge/src/main/java/dev/architectury/registry/registries/forge/RegistriesImpl.java @@ -21,10 +21,8 @@ package dev.architectury.registry.registries.forge; import com.google.common.base.Objects; import com.google.common.base.Suppliers; -import com.google.common.collect.HashBasedTable; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; -import com.google.common.collect.Table; import dev.architectury.platform.forge.EventBuses; import dev.architectury.registry.registries.Registrar; import dev.architectury.registry.registries.RegistrarBuilder; @@ -43,10 +41,7 @@ import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; import java.lang.reflect.Type; -import java.util.Iterator; -import java.util.Map; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.function.Consumer; import java.util.function.Supplier; @@ -67,10 +62,24 @@ public class RegistriesImpl { return null; } + public static class Data { + private boolean collected = false; + private final Map, Supplier>> objects = new LinkedHashMap<>(); + + public void register(IForgeRegistry registry, RegistryObject object, Supplier> reference) { + if (!collected) { + objects.put(object, reference); + } else { + registry.register(reference.get()); + object.updateReference(registry); + } + } + } + public static class RegistryProviderImpl implements Registries.RegistryProvider { private final String modId; private final Supplier eventBus; - private final Table, Supplier>> registry = HashBasedTable.create(); + private final Map registry = new HashMap<>(); private final Multimap>, Consumer>> listeners = HashMultimap.create(); public RegistryProviderImpl(String modId) { @@ -125,12 +134,18 @@ public class RegistriesImpl { IForgeRegistry registry = event.getRegistry(); Registrar archRegistry = get(registry); - for (Map.Entry, Supplier>>> row : RegistryProviderImpl.this.registry.rowMap().entrySet()) { - if (row.getKey() == event.getGenericType()) { - for (Map.Entry, Supplier>> entry : row.getValue().entrySet()) { + for (Map.Entry typeDataEntry : RegistryProviderImpl.this.registry.entrySet()) { + if (typeDataEntry.getKey() == registry.getRegistrySuperType()) { + Data data = typeDataEntry.getValue(); + + data.collected = true; + + for (Map.Entry, Supplier>> entry : data.objects.entrySet()) { registry.register(entry.getValue().get()); entry.getKey().updateReference(registry); } + + data.objects.clear(); } } @@ -291,9 +306,9 @@ public class RegistriesImpl { public static class ForgeBackedRegistryImpl> implements Registrar { private IForgeRegistry delegate; - private Table, Supplier>> registry; + private Map registry; - public ForgeBackedRegistryImpl(Table, Supplier>> registry, IForgeRegistry delegate) { + public ForgeBackedRegistryImpl(Map registry, IForgeRegistry delegate) { this.registry = registry; this.delegate = delegate; } @@ -345,7 +360,8 @@ public class RegistriesImpl { @Override public @NotNull RegistrySupplier register(ResourceLocation id, Supplier supplier) { RegistryObject registryObject = RegistryObject.of(id, delegate); - registry.put(delegate.getRegistrySuperType(), registryObject, () -> supplier.get().setRegistryName(id)); + registry.computeIfAbsent(delegate.getRegistrySuperType(), type -> new Data()) + .register(delegate, registryObject, () -> supplier.get().setRegistryName(id)); return new RegistrySupplier() { @Override public @NotNull ResourceLocation getRegistryId() { From b5aa583b02618697086479341aa55e51f5976edb Mon Sep 17 00:00:00 2001 From: shedaniel Date: Sat, 19 Feb 2022 00:43:41 +0800 Subject: [PATCH 4/5] [ci skip] Introduce item as an additional context (#189) * Introduce item as an additional context * Remove @Internal --- .../events/client/ClientTooltipEvent.java | 15 ++++++ .../impl/TooltipAdditionalContextsImpl.java | 46 +++++++++++++++++++ .../mixin/fabric/client/MixinScreen.java | 11 +++++ .../event/forge/EventHandlerImplClient.java | 46 +++++++++++-------- .../mixin/forge/MixinChunkSerializer.java | 2 +- 5 files changed, 101 insertions(+), 19 deletions(-) create mode 100644 common/src/main/java/dev/architectury/impl/TooltipAdditionalContextsImpl.java diff --git a/common/src/main/java/dev/architectury/event/events/client/ClientTooltipEvent.java b/common/src/main/java/dev/architectury/event/events/client/ClientTooltipEvent.java index dda4d077..20723ee0 100644 --- a/common/src/main/java/dev/architectury/event/events/client/ClientTooltipEvent.java +++ b/common/src/main/java/dev/architectury/event/events/client/ClientTooltipEvent.java @@ -23,12 +23,15 @@ import com.mojang.blaze3d.vertex.PoseStack; import dev.architectury.event.Event; import dev.architectury.event.EventFactory; import dev.architectury.event.EventResult; +import dev.architectury.impl.TooltipAdditionalContextsImpl; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -51,6 +54,18 @@ public interface ClientTooltipEvent { */ Event RENDER_MODIFY_COLOR = EventFactory.createLoop(); + static AdditionalContexts additionalContexts() { + return TooltipAdditionalContextsImpl.get(); + } + + @ApiStatus.NonExtendable + interface AdditionalContexts { + @Nullable + ItemStack getItem(); + + void setItem(@Nullable ItemStack stack); + } + @Environment(EnvType.CLIENT) interface Item { /** diff --git a/common/src/main/java/dev/architectury/impl/TooltipAdditionalContextsImpl.java b/common/src/main/java/dev/architectury/impl/TooltipAdditionalContextsImpl.java new file mode 100644 index 00000000..3392eca8 --- /dev/null +++ b/common/src/main/java/dev/architectury/impl/TooltipAdditionalContextsImpl.java @@ -0,0 +1,46 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021, 2022 architectury + * + * This program 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; either + * version 3 of the License, or (at your option) any later version. + * + * This program 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 program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package dev.architectury.impl; + +import dev.architectury.event.events.client.ClientTooltipEvent; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +public class TooltipAdditionalContextsImpl implements ClientTooltipEvent.AdditionalContexts { + private static final ThreadLocal INSTANCE_LOCAL = ThreadLocal.withInitial(TooltipAdditionalContextsImpl::new); + + public static ClientTooltipEvent.AdditionalContexts get() { + return INSTANCE_LOCAL.get(); + } + + @Nullable + private ItemStack item; + + @Override + @Nullable + public ItemStack getItem() { + return item; + } + + @Override + public void setItem(@Nullable ItemStack item) { + this.item = item; + } +} diff --git a/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinScreen.java b/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinScreen.java index 3c3c4bc5..3e1ff1c6 100644 --- a/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinScreen.java +++ b/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinScreen.java @@ -32,6 +32,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -98,6 +99,16 @@ public abstract class MixinScreen implements ScreenInputDelegate { return message; } + @Inject(method = "renderTooltip(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/world/item/ItemStack;II)V", at = @At("HEAD")) + private void preRenderTooltipItem(PoseStack poseStack, ItemStack stack, int x, int y, CallbackInfo ci) { + ClientTooltipEvent.additionalContexts().setItem(stack); + } + + @Inject(method = "renderTooltip(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/world/item/ItemStack;II)V", at = @At("RETURN")) + private void postRenderTooltipItem(PoseStack poseStack, ItemStack stack, int x, int y, CallbackInfo ci) { + ClientTooltipEvent.additionalContexts().setItem(null); + } + @Inject(method = "renderTooltipInternal", at = @At("HEAD"), cancellable = true) private void renderTooltip(PoseStack poseStack, List list, int x, int y, CallbackInfo ci) { if (!list.isEmpty()) { diff --git a/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java b/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java index 57b6ecee..f45685ba 100644 --- a/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java +++ b/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java @@ -171,32 +171,42 @@ public class EventHandlerImplClient { @SubscribeEvent(priority = EventPriority.HIGH) public static void event(RenderTooltipEvent.Pre event) { PoseStack stack = event.getPoseStack(); + ClientTooltipEvent.additionalContexts().setItem(event.getItemStack()); - if (ClientTooltipEvent.RENDER_PRE.invoker().renderTooltip(stack, event.getComponents(), event.getX(), event.getY()).isFalse()) { - event.setCanceled(true); - return; + try { + if (ClientTooltipEvent.RENDER_PRE.invoker().renderTooltip(stack, event.getComponents(), event.getX(), event.getY()).isFalse()) { + event.setCanceled(true); + return; + } + + TooltipEventPositionContextImpl positionContext = tooltipPositionContext.get(); + positionContext.reset(event.getX(), event.getY()); + ClientTooltipEvent.RENDER_MODIFY_POSITION.invoker().renderTooltip(stack, positionContext); + event.setX(positionContext.getTooltipX()); + event.setY(positionContext.getTooltipY()); + } finally { + ClientTooltipEvent.additionalContexts().setItem(null); } - - TooltipEventPositionContextImpl positionContext = tooltipPositionContext.get(); - positionContext.reset(event.getX(), event.getY()); - ClientTooltipEvent.RENDER_MODIFY_POSITION.invoker().renderTooltip(stack, positionContext); - event.setX(positionContext.getTooltipX()); - event.setY(positionContext.getTooltipY()); } @SubscribeEvent(priority = EventPriority.HIGH) public static void event(RenderTooltipEvent.Color event) { PoseStack stack = event.getPoseStack(); + ClientTooltipEvent.additionalContexts().setItem(event.getItemStack()); - TooltipEventColorContextImpl colorContext = tooltipColorContext.get(); - colorContext.reset(); - colorContext.setBackgroundColor(event.getBackgroundStart()); - colorContext.setOutlineGradientTopColor(event.getBorderStart()); - colorContext.setOutlineGradientBottomColor(event.getBorderEnd()); - ClientTooltipEvent.RENDER_MODIFY_COLOR.invoker().renderTooltip(stack, event.getX(), event.getY(), colorContext); - event.setBackground(colorContext.getBackgroundColor()); - event.setBorderEnd(colorContext.getOutlineGradientBottomColor()); - event.setBorderStart(colorContext.getOutlineGradientTopColor()); + try { + TooltipEventColorContextImpl colorContext = tooltipColorContext.get(); + colorContext.reset(); + colorContext.setBackgroundColor(event.getBackgroundStart()); + colorContext.setOutlineGradientTopColor(event.getBorderStart()); + colorContext.setOutlineGradientBottomColor(event.getBorderEnd()); + ClientTooltipEvent.RENDER_MODIFY_COLOR.invoker().renderTooltip(stack, event.getX(), event.getY(), colorContext); + event.setBackground(colorContext.getBackgroundColor()); + event.setBorderEnd(colorContext.getOutlineGradientBottomColor()); + event.setBorderStart(colorContext.getOutlineGradientTopColor()); + } finally { + ClientTooltipEvent.additionalContexts().setItem(null); + } } @SubscribeEvent(priority = EventPriority.HIGH) diff --git a/forge/src/main/java/dev/architectury/mixin/forge/MixinChunkSerializer.java b/forge/src/main/java/dev/architectury/mixin/forge/MixinChunkSerializer.java index 5df87a83..ccdc9739 100644 --- a/forge/src/main/java/dev/architectury/mixin/forge/MixinChunkSerializer.java +++ b/forge/src/main/java/dev/architectury/mixin/forge/MixinChunkSerializer.java @@ -59,7 +59,7 @@ public class MixinChunkSerializer { ChunkDataEvent.Load load = (ChunkDataEvent.Load) event; ((EventHandlerImplCommon.WorldEventAttachment) load).architectury$attachLevel(levelRef.get()); } - level.set(null); + level.remove(); return event; } } From 4c5bb1e8a526d796193228b06c5b517fca177f78 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Sat, 19 Feb 2022 00:45:45 +0800 Subject: [PATCH 5/5] Bump to 3.7 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 5657b2c4..8a039906 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ cf_type=release archives_base_name=architectury archives_base_name_snapshot=architectury-snapshot -base_version=3.6 +base_version=3.7 maven_group=dev.architectury fabric_loader_version=0.12.12