diff --git a/paper-api/src/main/java/io/papermc/paper/event/entity/GolemConstructEvent.java b/paper-api/src/main/java/io/papermc/paper/event/entity/GolemConstructEvent.java
new file mode 100644
index 000000000000..5f466ed97c29
--- /dev/null
+++ b/paper-api/src/main/java/io/papermc/paper/event/entity/GolemConstructEvent.java
@@ -0,0 +1,66 @@
+package io.papermc.paper.event.entity;
+
+import org.bukkit.block.Block;
+import org.bukkit.entity.Golem;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityEvent;
+import org.bukkit.event.entity.EntitySpawnEvent;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Unmodifiable;
+import org.jspecify.annotations.NullMarked;
+import java.util.List;
+
+/**
+ * Called just before a {@link Golem} spawns due to a pattern of blocks being constructed.
+ *
+ * Note: This event is fired before {@link EntitySpawnEvent}, before the golem is added to the world,
+ * the success of this event does not guarantee the golem will actually spawn.
+ */
+@NullMarked
+public class GolemConstructEvent extends EntityEvent implements Cancellable {
+
+ private static final HandlerList HANDLER_LIST = new HandlerList();
+
+ private final List blocks;
+ private boolean cancelled;
+
+ @ApiStatus.Internal
+ public GolemConstructEvent(Golem golem, List blocks) {
+ super(golem);
+ this.blocks = List.copyOf(blocks);
+ }
+
+ @Override
+ public Golem getEntity() {
+ return (Golem) super.getEntity();
+ }
+
+ /**
+ * Get an immutable list of the blocks for this golem
+ *
+ * @return the golem blocks
+ */
+ public @Unmodifiable List getBlocks() {
+ return blocks;
+ }
+
+ @Override
+ public void setCancelled(final boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLER_LIST;
+ }
+
+ public static HandlerList getHandlerList() {
+ return HANDLER_LIST;
+ }
+}
diff --git a/paper-server/patches/sources/net/minecraft/world/level/block/CarvedPumpkinBlock.java.patch b/paper-server/patches/sources/net/minecraft/world/level/block/CarvedPumpkinBlock.java.patch
index 53f2111574c8..ce9a06013c66 100644
--- a/paper-server/patches/sources/net/minecraft/world/level/block/CarvedPumpkinBlock.java.patch
+++ b/paper-server/patches/sources/net/minecraft/world/level/block/CarvedPumpkinBlock.java.patch
@@ -8,7 +8,7 @@
this.replaceCopperBlockWithChest(level, copperGolemMatch);
copperGolem.spawn(this.getWeatherStateFromPattern(copperGolemMatch));
}
-@@ -105,9 +_,22 @@
+@@ -105,9 +_,32 @@
}
private static void spawnGolemInWorld(final Level level, final BlockPattern.BlockPatternMatch match, final Entity golem, final BlockPos spawnPos) {
@@ -17,6 +17,16 @@
golem.snapTo(spawnPos.getX() + 0.5, spawnPos.getY() + 0.05, spawnPos.getZ() + 0.5, 0.0F, 0.0F);
- level.addFreshEntity(golem);
+ // Paper start
++ java.util.List blocks = new java.util.ArrayList<>();
++ for (int x = 0; x < match.getWidth(); x++) {
++ for (int y = 0; y < match.getHeight(); y++) {
++ BlockInWorld block = match.getBlock(x, y, 0);
++ blocks.add(org.bukkit.craftbukkit.block.CraftBlock.at(level, block.getPos()));
++ }
++ }
++ if (!new io.papermc.paper.event.entity.GolemConstructEvent((org.bukkit.entity.Golem) golem.getBukkitEntity(), blocks).callEvent()) {
++ return;
++ }
+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason;
+ if (golem.getType() == net.minecraft.world.entity.EntityType.SNOW_GOLEM) {
+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BUILD_SNOWMAN;