From 8d216ec8c3689bce00b4ec2bfbda682278be3bb8 Mon Sep 17 00:00:00 2001 From: Alejandro Nieto Date: Wed, 29 Oct 2025 19:48:27 +0100 Subject: [PATCH 1/4] Add CopperGolemWeatheringEvent --- .../entity/CopperGolemWeatheringEvent.java | 77 +++++++++++++++++++ .../animal/coppergolem/CopperGolem.java.patch | 20 +++++ 2 files changed, 97 insertions(+) create mode 100644 paper-api/src/main/java/io/papermc/paper/event/entity/CopperGolemWeatheringEvent.java diff --git a/paper-api/src/main/java/io/papermc/paper/event/entity/CopperGolemWeatheringEvent.java b/paper-api/src/main/java/io/papermc/paper/event/entity/CopperGolemWeatheringEvent.java new file mode 100644 index 000000000000..f00502f609e5 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/event/entity/CopperGolemWeatheringEvent.java @@ -0,0 +1,77 @@ +package io.papermc.paper.event.entity; + +import io.papermc.paper.world.WeatheringCopperState; +import org.bukkit.entity.CopperGolem; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.EntityEvent; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Called when a {@link CopperGolem} transitions from one {@link WeatheringCopperState} to another. + */ +@NullMarked +public class CopperGolemWeatheringEvent extends EntityEvent implements Cancellable { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final WeatheringCopperState weatherState; + private final WeatheringCopperState nextWeatherState; + + private boolean cancelled; + + @ApiStatus.Internal + public CopperGolemWeatheringEvent(final CopperGolem golem, final WeatheringCopperState weatherState, final WeatheringCopperState nextWeatherState) { + super(golem); + this.weatherState = weatherState; + this.nextWeatherState = nextWeatherState; + } + + /** + * Gets the copper golem entity that is about to weather. + * + * @return The copper golem entity about to weather. + */ + @Override + public CopperGolem getEntity() { + return (CopperGolem) super.getEntity(); + } + + /** + * Gets the current weathering state of the copper golem. + * + * @return The current weathering state. + */ + public WeatheringCopperState getWeatheringState() { + return weatherState; + } + + /** + * Gets the next weathering state the copper golem will transition to. + * + * @return The next weathering state. + */ + public WeatheringCopperState getNextWeatheringState() { + return nextWeatherState; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(final boolean cancel) { + this.cancelled = cancel; + } + + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } +} diff --git a/paper-server/patches/sources/net/minecraft/world/entity/animal/coppergolem/CopperGolem.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/animal/coppergolem/CopperGolem.java.patch index 67806aa82794..29b3a909cdc4 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/animal/coppergolem/CopperGolem.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/animal/coppergolem/CopperGolem.java.patch @@ -37,6 +37,26 @@ this.gameEvent(GameEvent.SHEAR, player); itemInHand.hurtAndBreak(1, player, hand); } +@@ -267,9 +_,18 @@ + boolean flag = weatherState.equals(WeatheringCopper.WeatherState.OXIDIZED); + if (gameTime >= this.nextWeatheringTick && !flag) { + WeatheringCopper.WeatherState weatherState1 = weatherState.next(); ++ // Paper start - CopperGolemWeatheringEvent ++ io.papermc.paper.event.entity.CopperGolemWeatheringEvent event = new io.papermc.paper.event.entity.CopperGolemWeatheringEvent( ++ (org.bukkit.entity.CopperGolem) this.getBukkitEntity(), ++ io.papermc.paper.world.WeatheringCopperState.valueOf(weatherState.name()), ++ io.papermc.paper.world.WeatheringCopperState.valueOf(weatherState1.name()) ++ ); ++ event.callEvent(); ++ // Paper end - CopperGolemWeatheringEvent + boolean flag1 = weatherState1.equals(WeatheringCopper.WeatherState.OXIDIZED); +- this.setWeatherState(weatherState1); ++ if (!event.isCancelled()) this.setWeatherState(weatherState1); // Paper - CopperGolemWeatheringEvent + this.nextWeatheringTick = flag1 ? 0L : this.nextWeatheringTick + random.nextIntBetweenInclusive(504000, 552000); ++ if (event.isCancelled()) return; // Paper - CopperGolemWeatheringEvent + } + + if (flag && this.canTurnToStatue(level)) { @@ -285,20 +_,27 @@ private void turnToStatue(ServerLevel level) { From 13744cc5a4e8ba7934eb2ebbef2843bf20deb576 Mon Sep 17 00:00:00 2001 From: Alejandro Nieto Date: Thu, 30 Oct 2025 18:54:16 +0100 Subject: [PATCH 2/4] Empty commit for CI rerun From c54aa9d90523389dafc5a70ada66ba9746a334de Mon Sep 17 00:00:00 2001 From: Alejandro Nieto Date: Sun, 2 Nov 2025 21:11:55 +0100 Subject: [PATCH 3/4] [ci skip] Naming consistency --- .../paper/event/entity/CopperGolemWeatheringEvent.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/paper-api/src/main/java/io/papermc/paper/event/entity/CopperGolemWeatheringEvent.java b/paper-api/src/main/java/io/papermc/paper/event/entity/CopperGolemWeatheringEvent.java index f00502f609e5..ca6e3bc62547 100644 --- a/paper-api/src/main/java/io/papermc/paper/event/entity/CopperGolemWeatheringEvent.java +++ b/paper-api/src/main/java/io/papermc/paper/event/entity/CopperGolemWeatheringEvent.java @@ -16,15 +16,15 @@ public class CopperGolemWeatheringEvent extends EntityEvent implements Cancellab private static final HandlerList HANDLER_LIST = new HandlerList(); - private final WeatheringCopperState weatherState; + private final WeatheringCopperState currentWeatherState; private final WeatheringCopperState nextWeatherState; private boolean cancelled; @ApiStatus.Internal - public CopperGolemWeatheringEvent(final CopperGolem golem, final WeatheringCopperState weatherState, final WeatheringCopperState nextWeatherState) { + public CopperGolemWeatheringEvent(final CopperGolem golem, final WeatheringCopperState currentWeatherState, final WeatheringCopperState nextWeatherState) { super(golem); - this.weatherState = weatherState; + this.currentWeatherState = currentWeatherState; this.nextWeatherState = nextWeatherState; } @@ -43,8 +43,8 @@ public CopperGolem getEntity() { * * @return The current weathering state. */ - public WeatheringCopperState getWeatheringState() { - return weatherState; + public WeatheringCopperState getCurrentWeatheringState() { + return currentWeatherState; } /** From bf7729837a53964d4d0c5a5ea63b41bd76ed8a43 Mon Sep 17 00:00:00 2001 From: Alejandro Nieto Date: Sun, 2 Nov 2025 21:14:54 +0100 Subject: [PATCH 4/4] Fire event on axe interaction and on lightning strike --- .../animal/coppergolem/CopperGolem.java.patch | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/paper-server/patches/sources/net/minecraft/world/entity/animal/coppergolem/CopperGolem.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/animal/coppergolem/CopperGolem.java.patch index 29b3a909cdc4..0692e975493f 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/animal/coppergolem/CopperGolem.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/animal/coppergolem/CopperGolem.java.patch @@ -37,6 +37,21 @@ this.gameEvent(GameEvent.SHEAR, player); itemInHand.hurtAndBreak(1, player, hand); } +@@ -245,6 +_,14 @@ + if (itemInHand.is(ItemTags.AXES)) { + WeatheringCopper.WeatherState weatherState = this.getWeatherState(); + if (weatherState != WeatheringCopper.WeatherState.UNAFFECTED) { ++ // Paper start - CopperGolemWeatheringEvent ++ io.papermc.paper.event.entity.CopperGolemWeatheringEvent event = new io.papermc.paper.event.entity.CopperGolemWeatheringEvent( ++ (org.bukkit.entity.CopperGolem) this.getBukkitEntity(), ++ io.papermc.paper.world.WeatheringCopperState.valueOf(weatherState.name()), ++ io.papermc.paper.world.WeatheringCopperState.valueOf(weatherState.previous().name()) ++ ); ++ if (!event.callEvent()) return InteractionResult.FAIL; ++ // Paper end - CopperGolemWeatheringEvent + level.playSound(null, this, SoundEvents.AXE_SCRAPE, this.getSoundSource(), 1.0F, 1.0F); + level.levelEvent(this, LevelEvent.PARTICLES_SCRAPE, this.blockPosition(), 0); + this.nextWeatheringTick = -1L; @@ -267,9 +_,18 @@ boolean flag = weatherState.equals(WeatheringCopper.WeatherState.OXIDIZED); if (gameTime >= this.nextWeatheringTick && !flag) { @@ -144,3 +159,18 @@ } @Override +@@ -461,6 +_,14 @@ + this.lastLightningBoltUUID = uuid; + WeatheringCopper.WeatherState weatherState = this.getWeatherState(); + if (weatherState != WeatheringCopper.WeatherState.UNAFFECTED) { ++ // Paper start - CopperGolemWeatheringEvent ++ io.papermc.paper.event.entity.CopperGolemWeatheringEvent event = new io.papermc.paper.event.entity.CopperGolemWeatheringEvent( ++ (org.bukkit.entity.CopperGolem) this.getBukkitEntity(), ++ io.papermc.paper.world.WeatheringCopperState.valueOf(weatherState.name()), ++ io.papermc.paper.world.WeatheringCopperState.valueOf(weatherState.previous().name()) ++ ); ++ if (!event.callEvent()) return; ++ // Paper end - CopperGolemWeatheringEvent + this.nextWeatheringTick = -1L; + this.entityData.set(DATA_WEATHER_STATE, weatherState.previous(), true); + }