From db14cbb0e0bdae22a6917b7eb63c80a4d8205a77 Mon Sep 17 00:00:00 2001
From: 28Pollux28 <40760287+28Pollux28@users.noreply.github.com>
Date: Sat, 3 Sep 2022 21:17:16 +0200
Subject: [PATCH] [1.19.X] Adding more precise events for Advancements (#8360)
---
.../server/PlayerAdvancements.java.patch | 17 ++-
.../net/minecraftforge/common/ForgeHooks.java | 4 +
.../event/ForgeEventFactory.java | 20 ++++
.../event/entity/player/AdvancementEvent.java | 105 ++++++++++++++++++
.../entity/player/AdvancementEventTest.java | 64 +++++++++++
src/test/resources/META-INF/mods.toml | 2 +
6 files changed, 211 insertions(+), 1 deletion(-)
create mode 100644 src/test/java/net/minecraftforge/debug/entity/player/AdvancementEventTest.java
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.