diff --git a/patches/minecraft/net/minecraft/server/PlayerAdvancements.java.patch b/patches/minecraft/net/minecraft/server/PlayerAdvancements.java.patch index 11a72f7b22..969814890a 100644 --- a/patches/minecraft/net/minecraft/server/PlayerAdvancements.java.patch +++ b/patches/minecraft/net/minecraft/server/PlayerAdvancements.java.patch @@ -20,11 +20,26 @@ boolean flag = false; AdvancementProgress advancementprogress = this.m_135996_(p_135989_); boolean flag1 = advancementprogress.m_8193_(); -@@ -248,6 +_,7 @@ +@@ -243,11 +_,14 @@ + this.m_136008_(p_135989_); + this.f_135967_.add(p_135989_); + flag = true; ++ net.minecraftforge.event.ForgeEventFactory.onAdvancementProgressedEvent(this.f_135968_, p_135989_, advancementprogress, p_135990_, net.minecraftforge.event.entity.player.AdvancementEvent.AdvancementProgressEvent.ProgressType.GRANT); + if (!flag1 && advancementprogress.m_8193_()) { + p_135989_.m_138321_().m_9989_(this.f_135968_); if (p_135989_.m_138320_() != null && p_135989_.m_138320_().m_14996_() && this.f_135968_.f_19853_.m_46469_().m_46207_(GameRules.f_46153_)) { this.f_135962_.m_240416_(Component.m_237110_("chat.type.advancement." + p_135989_.m_138320_().m_14992_().m_15548_(), this.f_135968_.m_5446_(), p_135989_.m_138330_()), false); } + net.minecraftforge.common.ForgeHooks.onAdvancement(this.f_135968_, p_135989_); ++ net.minecraftforge.event.ForgeEventFactory.onAdvancementEarnedEvent(this.f_135968_, p_135989_); } } +@@ -265,6 +_,7 @@ + this.m_136004_(p_135999_); + this.f_135967_.add(p_135999_); + flag = true; ++ net.minecraftforge.event.ForgeEventFactory.onAdvancementProgressedEvent(this.f_135968_, p_135999_, advancementprogress, p_136000_, net.minecraftforge.event.entity.player.AdvancementEvent.AdvancementProgressEvent.ProgressType.REVOKE); + } + + if (!advancementprogress.m_8206_()) { diff --git a/src/main/java/net/minecraftforge/common/ForgeHooks.java b/src/main/java/net/minecraftforge/common/ForgeHooks.java index f560bc00bf..a868c91f31 100644 --- a/src/main/java/net/minecraftforge/common/ForgeHooks.java +++ b/src/main/java/net/minecraftforge/common/ForgeHooks.java @@ -1030,6 +1030,10 @@ public class ForgeHooks return null; } + /** + * @deprecated See {@link ForgeEventFactory#onAdvancementEarnedEvent} and {@link ForgeEventFactory#onAdvancementProgressedEvent} + */ + @Deprecated(forRemoval = true, since = "1.19.2") public static void onAdvancement(ServerPlayer player, Advancement advancement) { MinecraftForge.EVENT_BUS.post(new AdvancementEvent(player, advancement)); diff --git a/src/main/java/net/minecraftforge/event/ForgeEventFactory.java b/src/main/java/net/minecraftforge/event/ForgeEventFactory.java index 60909c1d6b..1e6d9bb710 100644 --- a/src/main/java/net/minecraftforge/event/ForgeEventFactory.java +++ b/src/main/java/net/minecraftforge/event/ForgeEventFactory.java @@ -13,6 +13,9 @@ import java.util.function.Consumer; import com.mojang.authlib.GameProfile; import com.mojang.brigadier.CommandDispatcher; + +import net.minecraft.advancements.Advancement; +import net.minecraft.advancements.AdvancementProgress; import net.minecraft.commands.CommandBuildContext; import net.minecraft.server.MinecraftServer; import net.minecraft.server.ReloadableServerResources; @@ -97,6 +100,9 @@ import net.minecraftforge.event.entity.living.LivingPackSizeEvent; import net.minecraftforge.event.entity.living.LivingSpawnEvent; import net.minecraftforge.event.entity.living.LivingSpawnEvent.AllowDespawn; import net.minecraftforge.event.entity.living.ZombieEvent.SummonAidEvent; +import net.minecraftforge.event.entity.player.AdvancementEvent.AdvancementEarnEvent; +import net.minecraftforge.event.entity.player.AdvancementEvent.AdvancementProgressEvent; +import net.minecraftforge.event.entity.player.AdvancementEvent.AdvancementProgressEvent.ProgressType; import net.minecraftforge.event.entity.player.ArrowLooseEvent; import net.minecraftforge.event.entity.player.ArrowNockEvent; import net.minecraftforge.event.entity.player.BonemealEvent; @@ -129,6 +135,8 @@ import net.minecraftforge.event.level.LevelEvent; import net.minecraftforge.eventbus.api.Event; import net.minecraftforge.eventbus.api.Event.Result; import net.minecraftforge.fml.LogicalSide; + +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -820,4 +828,16 @@ public class ForgeEventFactory return WeightedRandomList.create(); return WeightedRandomList.create(event.getSpawnerDataList()); } + + @ApiStatus.Internal + public static void onAdvancementEarnedEvent(Player player, Advancement earned) + { + MinecraftForge.EVENT_BUS.post(new AdvancementEarnEvent(player, earned)); + } + + @ApiStatus.Internal + public static void onAdvancementProgressedEvent(Player player, Advancement progressed, AdvancementProgress advancementProgress, String criterion, ProgressType progressType) + { + MinecraftForge.EVENT_BUS.post(new AdvancementProgressEvent(player, progressed, advancementProgress, criterion, progressType)); + } } diff --git a/src/main/java/net/minecraftforge/event/entity/player/AdvancementEvent.java b/src/main/java/net/minecraftforge/event/entity/player/AdvancementEvent.java index de57b17ff6..eba0f29266 100644 --- a/src/main/java/net/minecraftforge/event/entity/player/AdvancementEvent.java +++ b/src/main/java/net/minecraftforge/event/entity/player/AdvancementEvent.java @@ -6,6 +6,7 @@ package net.minecraftforge.event.entity.player; import net.minecraft.advancements.Advancement; +import net.minecraft.advancements.AdvancementProgress; import net.minecraft.world.entity.player.Player; import net.minecraftforge.common.MinecraftForge; @@ -17,7 +18,9 @@ import net.minecraftforge.common.MinecraftForge; * This event does not have a result. {@link HasResult}
*
* This event is fired on the {@link MinecraftForge#EVENT_BUS}. + * @deprecated Use {@link net.minecraftforge.event.entity.player.AdvancementEvent.AdvancementEarnEvent} and {@link net.minecraftforge.event.entity.player.AdvancementEvent.AdvancementProgressEvent} instead */ +@Deprecated(since = "1.19.2") public class AdvancementEvent extends PlayerEvent { private final Advancement advancement; @@ -32,4 +35,106 @@ public class AdvancementEvent extends PlayerEvent { return advancement; } + + /** + * Fired when the player earns an advancement. An advancement is earned once its requirements are complete. + * + *

Note that advancements may be hidden from the player or used in background mechanics, such as recipe + * advancements for unlocking recipes in the recipe book.

+ * + *

This event is not {@linkplain net.minecraftforge.eventbus.api.Cancelable cancellable}, and does not {@linkplain HasResult have a result}.

+ * + *

This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus}, + * only on the {@linkplain net.minecraftforge.fml.LogicalSide#SERVER logical server}.

+ * + * @see AdvancementProgress#isDone() + */ + //todo: should extend AdvancementEvent in 1.20 + public static class AdvancementEarnEvent extends PlayerEvent + { + private final Advancement advancement; + + public AdvancementEarnEvent(Player player, Advancement earned) + { + super(player); + this.advancement = earned; + } + + /** + * + * {@return the advancement that was earned} + */ + public Advancement getAdvancement() + { + return advancement; + } + } + + /** + * Fired when the player's progress on an advancement criterion is granted or revoked. + * + *

This event is not {@linkplain net.minecraftforge.eventbus.api.Cancelable cancellable}, and does not {@linkplain HasResult have a result}.

+ * + *

This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus}, + * only on the {@linkplain net.minecraftforge.fml.LogicalSide#SERVER logical server}.

+ * + * @see AdvancementEarnEvent + * @see net.minecraft.server.PlayerAdvancements#award(Advancement, String) + * @see net.minecraft.server.PlayerAdvancements#revoke(Advancement, String) + */ + //todo: should extend AdvancementEvent in 1.20 + public static class AdvancementProgressEvent extends PlayerEvent + { + private final Advancement advancement; + private final AdvancementProgress advancementProgress; + private final String criterionName; + private final AdvancementEvent.AdvancementProgressEvent.ProgressType progressType; + + public AdvancementProgressEvent(Player player, Advancement progressed, AdvancementProgress advancementProgress, String criterionName, AdvancementEvent.AdvancementProgressEvent.ProgressType progressType) + { + super(player); + this.advancement = progressed; + this.advancementProgress = advancementProgress; + this.criterionName = criterionName; + this.progressType = progressType; + } + + /** + * + * {@return The advancement that was progressed} + */ + public Advancement getAdvancement() + { + return advancement; + } + + /** + * {@return the progress of the advancement} + */ + public AdvancementProgress getAdvancementProgress() + { + return advancementProgress; + } + + /** + * {@return name of the criterion that was progressed} + */ + public String getCriterionName() + { + return criterionName; + } + + /** + * {@return The type of progress for the criterion in this event} + */ + public ProgressType getProgressType() + { + return progressType; + } + + public enum ProgressType + { + GRANT, REVOKE + } + } } diff --git a/src/test/java/net/minecraftforge/debug/entity/player/AdvancementEventTest.java b/src/test/java/net/minecraftforge/debug/entity/player/AdvancementEventTest.java new file mode 100644 index 0000000000..6ef08ae611 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/entity/player/AdvancementEventTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.debug.entity.player; + +import net.minecraft.advancements.Advancement; +import net.minecraft.advancements.AdvancementProgress; +import net.minecraft.world.entity.player.Player; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.player.AdvancementEvent; +import net.minecraftforge.event.entity.player.AdvancementEvent.AdvancementEarnEvent; +import net.minecraftforge.event.entity.player.AdvancementEvent.AdvancementProgressEvent; +import net.minecraftforge.event.entity.player.AdvancementEvent.AdvancementProgressEvent.ProgressType; +import net.minecraftforge.fml.common.Mod; + +import org.slf4j.Logger; + +import com.mojang.logging.LogUtils; + +@Mod(AdvancementEventTest.MOD_ID) +public class AdvancementEventTest +{ + static final String MOD_ID = "advancement_event_test"; + private static final boolean ENABLED = false; + private static final Logger LOGGER = LogUtils.getLogger(); + + public AdvancementEventTest() + { + if (ENABLED) + { + MinecraftForge.EVENT_BUS.addListener(this::onAdvancementEarnEvent); + MinecraftForge.EVENT_BUS.addListener(this::onAdvancementProgressEvent); + } + } + + public void onAdvancementEarnEvent(AdvancementEarnEvent event) + { + Advancement advancement = event.getAdvancement(); + Player player = event.getEntity(); + LOGGER.info("Player {} earned advancement {} and was awarded {}", player, advancement.getId(), advancement.getRewards().toString()); + } + + public void onAdvancementProgressEvent(AdvancementProgressEvent event) + { + Advancement advancement = event.getAdvancement(); + Player player = event.getEntity(); + AdvancementProgress advancementProgress = event.getAdvancementProgress(); + String criterionName = event.getCriterionName(); + AdvancementEvent.AdvancementProgressEvent.ProgressType progressType = event.getProgressType(); + String action; + if (progressType == ProgressType.GRANT) + { + action = "granted"; + } + else + { + action = "revoked"; + } + LOGGER.info("Player {} progressed advancement {}. They were {} progress on {}. They have completed {}% of the achievement", + player, advancement.getId(), action, criterionName, advancementProgress.getPercent()*100); + } +} diff --git a/src/test/resources/META-INF/mods.toml b/src/test/resources/META-INF/mods.toml index d8a6fa92b3..00a34bd01b 100644 --- a/src/test/resources/META-INF/mods.toml +++ b/src/test/resources/META-INF/mods.toml @@ -15,6 +15,8 @@ license="LGPL v2.1" [[mods]] modId="potentialspawnsevent_test" +[[mods]] + modId="advancement_event_test" # LEGACY TEST CASES ###### The mods below are from the old test framework and need to be yeeted later again.