From 0cdecda840446b0e846bd171b39f6d5edfbbb60c Mon Sep 17 00:00:00 2001 From: shedaniel Date: Sat, 2 Jan 2021 01:20:40 +0800 Subject: [PATCH 1/8] Limit GuiEvent.DEBUG_TEXT to when f3 menu is enabled. --- .../architectury/event/forge/EventHandlerImplClient.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImplClient.java b/forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImplClient.java index c08a9c10..5560af6e 100644 --- a/forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImplClient.java +++ b/forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImplClient.java @@ -93,8 +93,10 @@ public class EventHandlerImplClient { @SubscribeEvent public static void event(RenderGameOverlayEvent.Text event) { - GuiEvent.DEBUG_TEXT_LEFT.invoker().gatherText(event.getLeft()); - GuiEvent.DEBUG_TEXT_RIGHT.invoker().gatherText(event.getRight()); + if (Minecraft.getInstance().options.renderDebug) { + GuiEvent.DEBUG_TEXT_LEFT.invoker().gatherText(event.getLeft()); + GuiEvent.DEBUG_TEXT_RIGHT.invoker().gatherText(event.getRight()); + } } @SubscribeEvent From f09f23db35d13dcf0a018638775336b8f2f65d95 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Thu, 7 Jan 2021 01:14:37 +0800 Subject: [PATCH 2/8] Adds CriteriaTriggersRegistry --- .../architectury/registry/CreativeTabs.java | 2 +- .../registry/CriteriaTriggersRegistry.java | 20 +++++++++++++++++++ .../fabric/CriteriaTriggersRegistryImpl.java | 10 ++++++++++ .../main/resources/architectury.accessWidener | 3 ++- .../forge/CriteriaTriggersRegistryImpl.java | 10 ++++++++++ 5 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 common/src/main/java/me/shedaniel/architectury/registry/CriteriaTriggersRegistry.java create mode 100644 fabric/src/main/java/me/shedaniel/architectury/registry/fabric/CriteriaTriggersRegistryImpl.java create mode 100644 forge/src/main/java/me/shedaniel/architectury/registry/forge/CriteriaTriggersRegistryImpl.java diff --git a/common/src/main/java/me/shedaniel/architectury/registry/CreativeTabs.java b/common/src/main/java/me/shedaniel/architectury/registry/CreativeTabs.java index 002e6303..59b005e8 100644 --- a/common/src/main/java/me/shedaniel/architectury/registry/CreativeTabs.java +++ b/common/src/main/java/me/shedaniel/architectury/registry/CreativeTabs.java @@ -27,7 +27,7 @@ import net.minecraft.world.item.ItemStack; import java.util.function.Supplier; public final class CreativeTabs { - public CreativeTabs() {} + private CreativeTabs() {} // I am sorry, fabric wants a resource location instead of the translation key for whatever reason @ExpectPlatform diff --git a/common/src/main/java/me/shedaniel/architectury/registry/CriteriaTriggersRegistry.java b/common/src/main/java/me/shedaniel/architectury/registry/CriteriaTriggersRegistry.java new file mode 100644 index 00000000..50e953f3 --- /dev/null +++ b/common/src/main/java/me/shedaniel/architectury/registry/CriteriaTriggersRegistry.java @@ -0,0 +1,20 @@ +package me.shedaniel.architectury.registry; + +import me.shedaniel.architectury.ExpectPlatform; +import net.minecraft.advancements.CriterionTrigger; + +public final class CriteriaTriggersRegistry { + private CriteriaTriggersRegistry() {} + + /** + * Invokes {@link net.minecraft.advancements.CriteriaTriggers#register(CriterionTrigger)}. + * + * @param trigger The trigger to register + * @param The type of trigger + * @return The trigger registered + */ + @ExpectPlatform + public static > T register(T trigger) { + throw new AssertionError(); + } +} diff --git a/fabric/src/main/java/me/shedaniel/architectury/registry/fabric/CriteriaTriggersRegistryImpl.java b/fabric/src/main/java/me/shedaniel/architectury/registry/fabric/CriteriaTriggersRegistryImpl.java new file mode 100644 index 00000000..70539e35 --- /dev/null +++ b/fabric/src/main/java/me/shedaniel/architectury/registry/fabric/CriteriaTriggersRegistryImpl.java @@ -0,0 +1,10 @@ +package me.shedaniel.architectury.registry.fabric; + +import net.minecraft.advancements.CriteriaTriggers; +import net.minecraft.advancements.CriterionTrigger; + +public class CriteriaTriggersRegistryImpl { + public static > T register(T trigger) { + return CriteriaTriggers.register(trigger); + } +} diff --git a/fabric/src/main/resources/architectury.accessWidener b/fabric/src/main/resources/architectury.accessWidener index 27a3797b..c0361a72 100644 --- a/fabric/src/main/resources/architectury.accessWidener +++ b/fabric/src/main/resources/architectury.accessWidener @@ -51,4 +51,5 @@ accessible method net/minecraft/world/entity/Entity getEncodeId ()Ljava/lang/Str accessible field net/minecraft/server/packs/repository/PackRepository sources Ljava/util/Set; mutable field net/minecraft/server/packs/repository/PackRepository sources Ljava/util/Set; accessible field net/minecraft/world/item/DyeColor textureDiffuseColor I -accessible method net/minecraft/world/entity/player/Player closeContainer ()V \ No newline at end of file +accessible method net/minecraft/world/entity/player/Player closeContainer ()V +accessible method net/minecraft/advancements/CriteriaTriggers register (Lnet/minecraft/advancements/CriterionTrigger;)Lnet/minecraft/advancements/CriterionTrigger; \ No newline at end of file diff --git a/forge/src/main/java/me/shedaniel/architectury/registry/forge/CriteriaTriggersRegistryImpl.java b/forge/src/main/java/me/shedaniel/architectury/registry/forge/CriteriaTriggersRegistryImpl.java new file mode 100644 index 00000000..ef812f30 --- /dev/null +++ b/forge/src/main/java/me/shedaniel/architectury/registry/forge/CriteriaTriggersRegistryImpl.java @@ -0,0 +1,10 @@ +package me.shedaniel.architectury.registry.forge; + +import net.minecraft.advancements.CriteriaTriggers; +import net.minecraft.advancements.CriterionTrigger; + +public class CriteriaTriggersRegistryImpl { + public static > T register(T trigger) { + return CriteriaTriggers.register(trigger); + } +} From e7e995f0b6e1e26e322af1cf4c3915d5a1565bc1 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Fri, 8 Jan 2021 01:28:04 +0800 Subject: [PATCH 3/8] Add license to CriteriaTriggersRegistry --- .../registry/CriteriaTriggersRegistry.java | 19 +++++++++++++++++++ .../fabric/CriteriaTriggersRegistryImpl.java | 19 +++++++++++++++++++ .../forge/CriteriaTriggersRegistryImpl.java | 19 +++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/common/src/main/java/me/shedaniel/architectury/registry/CriteriaTriggersRegistry.java b/common/src/main/java/me/shedaniel/architectury/registry/CriteriaTriggersRegistry.java index 50e953f3..8a8f16f6 100644 --- a/common/src/main/java/me/shedaniel/architectury/registry/CriteriaTriggersRegistry.java +++ b/common/src/main/java/me/shedaniel/architectury/registry/CriteriaTriggersRegistry.java @@ -1,3 +1,22 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021 shedaniel + * + * 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 me.shedaniel.architectury.registry; import me.shedaniel.architectury.ExpectPlatform; diff --git a/fabric/src/main/java/me/shedaniel/architectury/registry/fabric/CriteriaTriggersRegistryImpl.java b/fabric/src/main/java/me/shedaniel/architectury/registry/fabric/CriteriaTriggersRegistryImpl.java index 70539e35..24cf7c19 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/registry/fabric/CriteriaTriggersRegistryImpl.java +++ b/fabric/src/main/java/me/shedaniel/architectury/registry/fabric/CriteriaTriggersRegistryImpl.java @@ -1,3 +1,22 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021 shedaniel + * + * 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 me.shedaniel.architectury.registry.fabric; import net.minecraft.advancements.CriteriaTriggers; diff --git a/forge/src/main/java/me/shedaniel/architectury/registry/forge/CriteriaTriggersRegistryImpl.java b/forge/src/main/java/me/shedaniel/architectury/registry/forge/CriteriaTriggersRegistryImpl.java index ef812f30..0610c8e7 100644 --- a/forge/src/main/java/me/shedaniel/architectury/registry/forge/CriteriaTriggersRegistryImpl.java +++ b/forge/src/main/java/me/shedaniel/architectury/registry/forge/CriteriaTriggersRegistryImpl.java @@ -1,3 +1,22 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021 shedaniel + * + * 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 me.shedaniel.architectury.registry.forge; import net.minecraft.advancements.CriteriaTriggers; From 4981779d4b4ac439b4957e61e45276e8d74aae42 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Fri, 8 Jan 2021 01:28:22 +0800 Subject: [PATCH 4/8] Add getModId to Registries --- .../java/me/shedaniel/architectury/registry/Registries.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common/src/main/java/me/shedaniel/architectury/registry/Registries.java b/common/src/main/java/me/shedaniel/architectury/registry/Registries.java index 8662c884..40e48e1c 100644 --- a/common/src/main/java/me/shedaniel/architectury/registry/Registries.java +++ b/common/src/main/java/me/shedaniel/architectury/registry/Registries.java @@ -34,6 +34,7 @@ import java.util.concurrent.ConcurrentHashMap; public final class Registries { private static final Map REGISTRIES = new ConcurrentHashMap<>(); private final RegistryProvider provider; + private final String modId; public static Registries get(String modId) { return REGISTRIES.computeIfAbsent(modId, Registries::new); @@ -41,6 +42,7 @@ public final class Registries { private Registries(String modId) { this.provider = _get(modId); + this.modId = modId; } public Registry get(ResourceKey> key) { @@ -88,6 +90,10 @@ public final class Registries { throw new AssertionError(); } + public String getModId() { + return modId; + } + @ApiStatus.Internal public interface RegistryProvider { Registry get(ResourceKey> key); From d3a127f9952c888f74fe25a145cf356e198ba296 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Fri, 8 Jan 2021 01:28:53 +0800 Subject: [PATCH 5/8] Allow DeferredRegister to be created with just the mod id. --- .../registry/DeferredRegister.java | 53 +++++++++++++------ 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/common/src/main/java/me/shedaniel/architectury/registry/DeferredRegister.java b/common/src/main/java/me/shedaniel/architectury/registry/DeferredRegister.java index 18c6a974..2b6550ec 100644 --- a/common/src/main/java/me/shedaniel/architectury/registry/DeferredRegister.java +++ b/common/src/main/java/me/shedaniel/architectury/registry/DeferredRegister.java @@ -19,42 +19,65 @@ package me.shedaniel.architectury.registry; -import com.google.common.base.Objects; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.LazyLoadedValue; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.function.Supplier; public class DeferredRegister { + @NotNull private final Supplier registriesSupplier; + @NotNull private final ResourceKey> key; private final List> entries = new ArrayList<>(); private boolean registered = false; + @Nullable + private String modId; - private DeferredRegister(Supplier registriesSupplier, ResourceKey> key) { - this.registriesSupplier = registriesSupplier; - this.key = key; + private DeferredRegister(@NotNull Supplier registriesSupplier, @NotNull ResourceKey> key, @Nullable String modId) { + this.registriesSupplier = Objects.requireNonNull(registriesSupplier); + this.key = Objects.requireNonNull(key); + this.modId = modId; } @NotNull - public static DeferredRegister create(Registries registries, ResourceKey> key) { - return new DeferredRegister<>(() -> registries, key); + public static DeferredRegister create(@NotNull String modId, @NotNull ResourceKey> key) { + LazyLoadedValue value = new LazyLoadedValue<>(() -> Registries.get(modId)); + return new DeferredRegister<>(value::get, key, Objects.requireNonNull(modId)); } @NotNull - public static DeferredRegister create(Supplier registries, ResourceKey> key) { - return new DeferredRegister<>(registries, key); + @Deprecated + public static DeferredRegister create(@NotNull Registries registries, @NotNull ResourceKey> key) { + return new DeferredRegister<>(() -> registries, key, null); } @NotNull - public static DeferredRegister create(LazyLoadedValue registries, ResourceKey> key) { + @Deprecated + public static DeferredRegister create(@NotNull Supplier registries, @NotNull ResourceKey> key) { + return new DeferredRegister<>(registries, key, null); + } + + @NotNull + @Deprecated + public static DeferredRegister create(@NotNull LazyLoadedValue registries, @NotNull ResourceKey> key) { return create(registries::get, key); } + public RegistrySupplier register(String id, Supplier supplier) { + if (modId == null) { + throw new NullPointerException("You must create the deferred register with a mod id to register entries without the namespace!"); + } + + return register(new ResourceLocation(modId, id), supplier); + } + public RegistrySupplier register(ResourceLocation id, Supplier supplier) { Entry entry = new Entry<>(id, supplier); this.entries.add(entry); @@ -76,12 +99,12 @@ public class DeferredRegister { } } - private class Entry implements RegistrySupplier { + private class Entry implements RegistrySupplier { private final ResourceLocation id; - private final Supplier supplier; - private RegistrySupplier value; + private final Supplier supplier; + private RegistrySupplier value; - public Entry(ResourceLocation id, Supplier supplier) { + public Entry(ResourceLocation id, Supplier supplier) { this.id = id; this.supplier = supplier; } @@ -102,7 +125,7 @@ public class DeferredRegister { } @Override - public T get() { + public R get() { if (isPresent()) { return value.get(); } @@ -111,7 +134,7 @@ public class DeferredRegister { @Override public int hashCode() { - return Objects.hashCode(getRegistryId(), getId()); + return com.google.common.base.Objects.hashCode(getRegistryId(), getId()); } @Override From 12b3ffb909a327cf87bc30a4f356f2e80576bc5f Mon Sep 17 00:00:00 2001 From: shedaniel Date: Sat, 9 Jan 2021 18:46:16 +0800 Subject: [PATCH 6/8] Warn additional mod loaders. --- .../me/shedaniel/architectury/Architectury.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/common/src/main/java/me/shedaniel/architectury/Architectury.java b/common/src/main/java/me/shedaniel/architectury/Architectury.java index d9997fe7..2b7878fe 100644 --- a/common/src/main/java/me/shedaniel/architectury/Architectury.java +++ b/common/src/main/java/me/shedaniel/architectury/Architectury.java @@ -20,8 +20,11 @@ package me.shedaniel.architectury; import com.google.common.collect.ImmutableMap; +import org.apache.logging.log4j.LogManager; import org.jetbrains.annotations.ApiStatus; +import java.util.ArrayList; +import java.util.List; import java.util.Map; @ApiStatus.Internal @@ -37,16 +40,18 @@ public class Architectury { } static { - String loader = null; + List loader = new ArrayList<>(); for (Map.Entry entry : MOD_LOADERS.entrySet()) { try { Class.forName(entry.getKey(), false, Architectury.class.getClassLoader()); - loader = entry.getValue(); + loader.add(entry.getValue()); break; } catch (ClassNotFoundException ignored) {} } - if (loader == null) + if (loader.isEmpty()) throw new IllegalStateException("No detected mod loader!"); - MOD_LOADER = loader; + if (loader.size() >= 2) + LogManager.getLogger().error("Detected multiple mod loaders! Something is wrong on the classpath! " + String.join(", ", loader)); + MOD_LOADER = loader.get(0); } } From cd5d68e40c65d493fc8bad659ebce753227e7d82 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Sat, 9 Jan 2021 20:14:27 +0800 Subject: [PATCH 7/8] Fix some events --- .../architectury/event/events/PlayerEvent.java | 2 +- .../architectury/mixin/fabric/MixinItemEntity.java | 11 ++++++++++- .../architectury/mixin/fabric/MixinPlayer.java | 2 +- .../mixin/fabric/client/MixinMinecraft.java | 4 +++- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/common/src/main/java/me/shedaniel/architectury/event/events/PlayerEvent.java b/common/src/main/java/me/shedaniel/architectury/event/events/PlayerEvent.java index e1654c32..982e572f 100644 --- a/common/src/main/java/me/shedaniel/architectury/event/events/PlayerEvent.java +++ b/common/src/main/java/me/shedaniel/architectury/event/events/PlayerEvent.java @@ -71,7 +71,7 @@ public interface PlayerEvent { } interface CraftItem { - void craft(Player player, ItemStack smelted, Container inventory); + void craft(Player player, ItemStack constructed, Container inventory); } interface SmeltItem { diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinItemEntity.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinItemEntity.java index 01bb2dbd..a1cee332 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinItemEntity.java +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinItemEntity.java @@ -26,6 +26,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -35,9 +36,13 @@ public abstract class MixinItemEntity { @Shadow public abstract ItemStack getItem(); + @Unique + private ItemStack cache; + @Inject(method = "playerTouch", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;getCount()I"), cancellable = true) private void prePickup(Player player, CallbackInfo ci) { + cache = getItem().copy(); InteractionResult canPickUp = PlayerEvent.PICKUP_ITEM_PRE.invoker().canPickup(player, (ItemEntity) (Object) this, getItem()); if (canPickUp == InteractionResult.FAIL) { ci.cancel(); @@ -47,6 +52,10 @@ public abstract class MixinItemEntity { @Inject(method = "playerTouch", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;take(Lnet/minecraft/world/entity/Entity;I)V")) private void pickup(Player player, CallbackInfo ci) { - PlayerEvent.PICKUP_ITEM_POST.invoker().pickup(player, (ItemEntity) (Object) this, getItem()); + if (cache != null) { + PlayerEvent.PICKUP_ITEM_POST.invoker().pickup(player, (ItemEntity) (Object) this, cache); + } + + this.cache = null; } } \ No newline at end of file diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinPlayer.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinPlayer.java index 3bfd44a4..22fd42d5 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinPlayer.java +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinPlayer.java @@ -48,7 +48,7 @@ public class MixinPlayer { @Inject(method = "drop(Lnet/minecraft/world/item/ItemStack;ZZ)Lnet/minecraft/world/entity/item/ItemEntity;", at = @At("RETURN"), cancellable = true) private void drop(ItemStack itemStack, boolean bl, boolean bl2, CallbackInfoReturnable cir) { - if (PlayerEvent.DROP_ITEM.invoker().drop((Player) (Object) this, cir.getReturnValue()) == InteractionResult.FAIL) { + if (cir.getReturnValue() != null && PlayerEvent.DROP_ITEM.invoker().drop((Player) (Object) this, cir.getReturnValue()) == InteractionResult.FAIL) { cir.setReturnValue(null); } } diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinMinecraft.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinMinecraft.java index 5eaea2be..7ed0192c 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinMinecraft.java +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinMinecraft.java @@ -44,7 +44,9 @@ public class MixinMinecraft { @Inject(method = "clearLevel(Lnet/minecraft/client/gui/screens/Screen;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/chat/NarratorChatListener;clear()V")) private void handleLogin(Screen screen, CallbackInfo ci) { - ClientPlayerEvent.CLIENT_PLAYER_QUIT.invoker().quit(player); + if (player != null) { + ClientPlayerEvent.CLIENT_PLAYER_QUIT.invoker().quit(player); + } } @Inject(method = "startUseItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;isEmpty()Z", ordinal = 1), From 5b6f429bbeb0229410f94c466a45335d3b8c269d Mon Sep 17 00:00:00 2001 From: shedaniel Date: Sat, 9 Jan 2021 20:17:01 +0800 Subject: [PATCH 8/8] Add test mod --- build.gradle | 9 +- .../architectury/test/ConsoleMessageSink.java | 13 ++ .../architectury/test/MessageSink.java | 9 + .../shedaniel/architectury/test/TestMod.java | 211 ++++++++++++++++++ .../test/client/ClientOverlayMessageSink.java | 80 +++++++ common/src/test/resources/fabric.mod.json | 17 ++ fabric/build.gradle | 2 + 7 files changed, 339 insertions(+), 2 deletions(-) create mode 100644 common/src/test/java/me/shedaniel/architectury/test/ConsoleMessageSink.java create mode 100644 common/src/test/java/me/shedaniel/architectury/test/MessageSink.java create mode 100644 common/src/test/java/me/shedaniel/architectury/test/TestMod.java create mode 100644 common/src/test/java/me/shedaniel/architectury/test/client/ClientOverlayMessageSink.java create mode 100644 common/src/test/resources/fabric.mod.json diff --git a/build.gradle b/build.gradle index a6d6350f..afaef1e7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,6 @@ plugins { - id "architect-plugin" version "1.2.33" + id "architectury-plugin" version "1.3.41" + id "forgified-fabric-loom" version "0.5.22" apply false id "org.cadixdev.licenser" version "0.5.0" id "com.jfrog.bintray" version "1.8.4" id "com.matthewprenger.cursegradle" version "1.4.0" apply false @@ -13,11 +14,15 @@ architectury { subprojects { apply plugin: "forgified-fabric-loom" + + dependencies { + testCompile sourceSets.main.output + } } allprojects { apply plugin: "java" - apply plugin: "architect-plugin" + apply plugin: "architectury-plugin" apply plugin: "org.cadixdev.licenser" archivesBaseName = rootProject.archives_base_name diff --git a/common/src/test/java/me/shedaniel/architectury/test/ConsoleMessageSink.java b/common/src/test/java/me/shedaniel/architectury/test/ConsoleMessageSink.java new file mode 100644 index 00000000..289e7471 --- /dev/null +++ b/common/src/test/java/me/shedaniel/architectury/test/ConsoleMessageSink.java @@ -0,0 +1,13 @@ +package me.shedaniel.architectury.test; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ConsoleMessageSink implements MessageSink { + protected final Logger logger = LogManager.getLogger("Architectury Test"); + + @Override + public void accept(String message) { + logger.info(message); + } +} diff --git a/common/src/test/java/me/shedaniel/architectury/test/MessageSink.java b/common/src/test/java/me/shedaniel/architectury/test/MessageSink.java new file mode 100644 index 00000000..28710d5b --- /dev/null +++ b/common/src/test/java/me/shedaniel/architectury/test/MessageSink.java @@ -0,0 +1,9 @@ +package me.shedaniel.architectury.test; + +public interface MessageSink { + void accept(String message); + + default void accept(String message, Object... args) { + accept(String.format(message, args)); + } +} diff --git a/common/src/test/java/me/shedaniel/architectury/test/TestMod.java b/common/src/test/java/me/shedaniel/architectury/test/TestMod.java new file mode 100644 index 00000000..1bf85cd6 --- /dev/null +++ b/common/src/test/java/me/shedaniel/architectury/test/TestMod.java @@ -0,0 +1,211 @@ +package me.shedaniel.architectury.test; + +import me.shedaniel.architectury.event.events.*; +import me.shedaniel.architectury.event.events.client.ClientChatEvent; +import me.shedaniel.architectury.event.events.client.ClientLifecycleEvent; +import me.shedaniel.architectury.event.events.client.ClientPlayerEvent; +import me.shedaniel.architectury.hooks.ExplosionHooks; +import me.shedaniel.architectury.platform.Platform; +import me.shedaniel.architectury.test.client.ClientOverlayMessageSink; +import me.shedaniel.architectury.utils.Env; +import me.shedaniel.architectury.utils.EnvExecutor; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.core.Position; +import net.minecraft.core.Vec3i; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; + +import java.util.Optional; + +public class TestMod { + public static final MessageSink SINK = EnvExecutor.getEnvSpecific(() -> ClientOverlayMessageSink::new, () -> ConsoleMessageSink::new); + + public static void initialize() { + debugEvents(); + if (Platform.getEnvironment() == Env.CLIENT) + debugEventsClient(); + } + + public static void debugEvents() { + ChatEvent.SERVER.register((player, message, component) -> { + SINK.accept("Server chat received: " + message); + return InteractionResultHolder.pass(component); + }); + CommandPerformEvent.EVENT.register(event -> { + SINK.accept("Server command performed: " + event.getResults().getReader().getString()); + return InteractionResult.PASS; + }); + CommandRegistrationEvent.EVENT.register((dispatcher, selection) -> { + SINK.accept("Server commands registers"); + }); + EntityEvent.LIVING_DEATH.register((entity, source) -> { + if (entity instanceof Player) { + SINK.accept(entity.getScoreboardName() + " died to " + source.getMsgId() + logSide(entity.level)); + } + return InteractionResult.PASS; + }); + EntityEvent.LIVING_ATTACK.register((entity, source, amount) -> { + if (source.getDirectEntity() instanceof Player) { + SINK.accept(source.getDirectEntity().getScoreboardName() + " deals %.2f damage" + logSide(entity.level), amount); + } + return InteractionResult.PASS; + }); + EntityEvent.ADD.register((entity, level) -> { + if (entity instanceof Player) { + SINK.accept(entity.getScoreboardName() + " was added to " + level.dimension().location().toString() + logSide(level)); + } + return InteractionResult.PASS; + }); + EntityEvent.PLACE_BLOCK.register((world, pos, state, placer) -> { + SINK.accept(Optional.ofNullable(placer).map(Entity::getScoreboardName).orElse("null") + " places block at " + toShortString(pos) + logSide(world)); + return InteractionResult.PASS; + }); + ExplosionEvent.DETONATE.register((world, explosion, affectedEntities) -> { + SINK.accept(world.dimension().location() + " explodes at " + toShortString(ExplosionHooks.getPosition(explosion)) + logSide(world)); + }); + InteractionEvent.LEFT_CLICK_BLOCK.register((player, hand, pos, face) -> { + SINK.accept(player.getScoreboardName() + " left clicks " + toShortString(pos) + logSide(player.level)); + return InteractionResult.PASS; + }); + InteractionEvent.RIGHT_CLICK_BLOCK.register((player, hand, pos, face) -> { + SINK.accept(player.getScoreboardName() + " right clicks " + toShortString(pos) + logSide(player.level)); + return InteractionResult.PASS; + }); + InteractionEvent.RIGHT_CLICK_ITEM.register((player, hand) -> { + SINK.accept(player.getScoreboardName() + " uses " + (hand == InteractionHand.MAIN_HAND ? "main hand" : "off hand") + logSide(player.level)); + return InteractionResultHolder.pass(player.getItemInHand(hand)); + }); + InteractionEvent.INTERACT_ENTITY.register((player, entity, hand) -> { + SINK.accept(player.getScoreboardName() + " interacts with " + entity.getScoreboardName() + " using " + (hand == InteractionHand.MAIN_HAND ? "main hand" : "off hand") + logSide(player.level)); + return InteractionResult.PASS; + }); + LifecycleEvent.SERVER_BEFORE_START.register(instance -> { + SINK.accept("Server ready to start"); + }); + LifecycleEvent.SERVER_STARTING.register(instance -> { + SINK.accept("Server starting"); + }); + LifecycleEvent.SERVER_STARTED.register(instance -> { + SINK.accept("Server started"); + }); + LifecycleEvent.SERVER_STOPPING.register(instance -> { + SINK.accept("Server stopping"); + }); + LifecycleEvent.SERVER_STOPPED.register(instance -> { + SINK.accept("Server stopped"); + }); + LifecycleEvent.SERVER_WORLD_LOAD.register(instance -> { + SINK.accept("Server world loaded: " + instance.dimension().location()); + }); + LifecycleEvent.SERVER_WORLD_UNLOAD.register(instance -> { + SINK.accept("Server world unloaded: " + instance.dimension().location()); + }); + LifecycleEvent.SERVER_WORLD_SAVE.register(instance -> { + SINK.accept("Server world saved: " + instance.dimension().location()); + }); + PlayerEvent.PLAYER_JOIN.register(player -> { + SINK.accept(player.getScoreboardName() + " joined" + logSide(player.level)); + }); + PlayerEvent.PLAYER_QUIT.register(player -> { + SINK.accept(player.getScoreboardName() + " quit" + logSide(player.level)); + }); + PlayerEvent.PLAYER_RESPAWN.register((player, conqueredEnd) -> { + if (!conqueredEnd) { + SINK.accept(player.getScoreboardName() + " respawns " + logSide(player.level)); + } + }); + PlayerEvent.PLAYER_CLONE.register((oldPlayer, newPlayer, wonGame) -> { + SINK.accept("Player cloned: " + newPlayer.getScoreboardName() + logSide(newPlayer.level)); + }); + PlayerEvent.PLAYER_ADVANCEMENT.register((player, advancement) -> { + SINK.accept(player.getScoreboardName() + " was awarded with %s" + logSide(player.level), advancement.getChatComponent().getString()); + }); + PlayerEvent.CRAFT_ITEM.register((player, constructed, inventory) -> { + SINK.accept(player.getScoreboardName() + " crafts " + new TranslatableComponent(constructed.getDescriptionId()).getString() + logSide(player.level)); + }); + PlayerEvent.SMELT_ITEM.register((player, smelted) -> { + SINK.accept(player.getScoreboardName() + " smelts " + new TranslatableComponent(smelted.getDescriptionId()).getString() + logSide(player.level)); + }); + PlayerEvent.PICKUP_ITEM_POST.register((player, entity, stack) -> { + SINK.accept(player.getScoreboardName() + " picks up " + new TranslatableComponent(stack.getDescriptionId()).getString() + logSide(player.level)); + }); + PlayerEvent.DROP_ITEM.register((player, entity) -> { + SINK.accept(player.getScoreboardName() + " drops " + new TranslatableComponent(entity.getItem().getDescriptionId()).getString() + logSide(player.level)); + return InteractionResult.PASS; + }); + PlayerEvent.BREAK_BLOCK.register((world, pos, state, player, xp) -> { + SINK.accept(player.getScoreboardName() + " breaks " + toShortString(pos) + logSide(player.level)); + return InteractionResult.PASS; + }); + PlayerEvent.OPEN_MENU.register((player, menu) -> { + SINK.accept(player.getScoreboardName() + " opens " + toSimpleName(menu) + logSide(player.level)); + }); + PlayerEvent.CLOSE_MENU.register((player, menu) -> { + SINK.accept(player.getScoreboardName() + " closes " + toSimpleName(menu) + logSide(player.level)); + }); + } + + public static String toShortString(Vec3i pos) { + return pos.getX() + ", " + pos.getY() + ", " + pos.getZ(); + } + + public static String toShortString(Position pos) { + return pos.x() + ", " + pos.y() + ", " + pos.z(); + } + + public static String logSide(Level level) { + if (level.isClientSide()) + return " (client)"; + return " (server)"; + } + + @Environment(EnvType.CLIENT) + public static void debugEventsClient() { + ClientChatEvent.CLIENT.register(message -> { + SINK.accept("Client chat sent: " + message); + return InteractionResultHolder.pass(message); + }); + ClientChatEvent.CLIENT_RECEIVED.register((type, message, sender) -> { + SINK.accept("Client chat received: " + message.getString()); + return InteractionResultHolder.pass(message); + }); + ClientLifecycleEvent.CLIENT_WORLD_LOAD.register(world -> { + SINK.accept("Client world loaded: " + world.dimension().location().toString()); + }); + ClientPlayerEvent.CLIENT_PLAYER_JOIN.register(player -> { + SINK.accept(player.getScoreboardName() + " joined (client)"); + }); + ClientPlayerEvent.CLIENT_PLAYER_QUIT.register(player -> { + SINK.accept(player.getScoreboardName() + " quit (client)"); + }); + ClientPlayerEvent.CLIENT_PLAYER_RESPAWN.register((oldPlayer, newPlayer) -> { + SINK.accept(newPlayer.getScoreboardName() + " respawned (client)"); + }); + GuiEvent.INIT_PRE.register((screen, widgets, children) -> { + SINK.accept(toSimpleName(screen) + " initializes"); + return InteractionResult.PASS; + }); + InteractionEvent.CLIENT_LEFT_CLICK_AIR.register((player, hand) -> { + SINK.accept(player.getScoreboardName() + " left clicks air" + logSide(player.level)); + }); + InteractionEvent.CLIENT_RIGHT_CLICK_AIR.register((player, hand) -> { + SINK.accept(player.getScoreboardName() + " right clicks air" + logSide(player.level)); + }); + RecipeUpdateEvent.EVENT.register(recipeManager -> { + SINK.accept("Client recipes received"); + }); + TextureStitchEvent.POST.register(atlas -> { + SINK.accept("Client texture stitched: " + atlas.location()); + }); + } + + private static String toSimpleName(Object o) { + return o.getClass().getSimpleName() + "@" + Integer.toHexString(o.hashCode()); + } +} diff --git a/common/src/test/java/me/shedaniel/architectury/test/client/ClientOverlayMessageSink.java b/common/src/test/java/me/shedaniel/architectury/test/client/ClientOverlayMessageSink.java new file mode 100644 index 00000000..0af96bcd --- /dev/null +++ b/common/src/test/java/me/shedaniel/architectury/test/client/ClientOverlayMessageSink.java @@ -0,0 +1,80 @@ +package me.shedaniel.architectury.test.client; + +import com.google.common.collect.Lists; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.architectury.event.events.GuiEvent; +import me.shedaniel.architectury.test.ConsoleMessageSink; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.Util; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiComponent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.util.Mth; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +@Environment(EnvType.CLIENT) +public class ClientOverlayMessageSink extends ConsoleMessageSink { + private final List messages = Collections.synchronizedList(Lists.newArrayList()); + + public ClientOverlayMessageSink() { + GuiEvent.RENDER_POST.register((screen, matrices, mouseX, mouseY, delta) -> render(matrices, delta)); + GuiEvent.RENDER_HUD.register((matrices, tickDelta) -> { + if (Minecraft.getInstance().screen == null && !Minecraft.getInstance().options.renderDebug) { + render(matrices, tickDelta); + } + }); + } + + @Override + public void accept(String message) { + super.accept(message); + messages.add(0, new Message(new TextComponent(message), Util.getMillis())); + } + + public void render(PoseStack matrices, float delta) { + Minecraft minecraft = Minecraft.getInstance(); + long currentMills = Util.getMillis(); + int lineHeight = minecraft.font.lineHeight; + + synchronized (messages) { + Iterator messageIterator = messages.iterator(); + int y = 1; + + RenderSystem.enableBlend(); + + while (messageIterator.hasNext()) { + Message message = messageIterator.next(); + int timeExisted = (int) (currentMills - message.created); + + if (timeExisted >= 5000) { + messageIterator.remove(); + } else { + int textWidth = minecraft.font.width(message.text); + int alpha = (int) Mth.clamp((5000 - timeExisted) / 5000f * 400f + 8, 0, 255); + GuiComponent.fill(matrices, 0, y - 1, 2 + textWidth + 1, y + lineHeight - 1, 0x505050 + ((alpha * 144 / 255) << 24)); + minecraft.font.draw(matrices, message.text, 1, y, 0xE0E0E0 + (alpha << 24)); + y += lineHeight; + } + } + } + + RenderSystem.disableAlphaTest(); + RenderSystem.disableBlend(); + } + + private static class Message { + private final Component text; + private final long created; + + public Message(Component text, long created) { + this.text = text; + this.created = created; + } + } +} diff --git a/common/src/test/resources/fabric.mod.json b/common/src/test/resources/fabric.mod.json new file mode 100644 index 00000000..04202eb8 --- /dev/null +++ b/common/src/test/resources/fabric.mod.json @@ -0,0 +1,17 @@ +{ + "schemaVersion": 1, + "id": "architectury-test", + "version": "${version}", + "name": "Architectury Test", + "description": "A intermediary api aimed to ease developing multiplatform mods.", + "authors": [ + "shedaniel" + ], + "license": "LGPL-3", + "environment": "*", + "entrypoints": { + "main": [ + "me.shedaniel.architectury.test.TestMod::initialize" + ] + } +} \ No newline at end of file diff --git a/fabric/build.gradle b/fabric/build.gradle index 99c065b6..83353a7a 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -40,6 +40,8 @@ dependencies { shadow(project(path: ":common", configuration: "transformed")) { transitive = false } + + testCompile project(":common").sourceSets.test.output } processResources {