--- a/net/minecraft/world/entity/animal/SnowGolem.java
+++ b/net/minecraft/world/entity/animal/SnowGolem.java
@@ -2,6 +2,7 @@
 
 import javax.annotation.Nullable;
 import net.minecraft.core.BlockPos;
+import net.minecraft.core.Holder;
 import net.minecraft.nbt.CompoundTag;
 import net.minecraft.network.syncher.EntityDataAccessor;
 import net.minecraft.network.syncher.EntityDataSerializers;
@@ -14,6 +15,7 @@
 import net.minecraft.world.InteractionHand;
 import net.minecraft.world.InteractionResult;
 import net.minecraft.world.damagesource.DamageSource;
+import net.minecraft.world.entity.Entity;
 import net.minecraft.world.entity.EntityType;
 import net.minecraft.world.entity.LivingEntity;
 import net.minecraft.world.entity.Mob;
@@ -37,8 +39,12 @@
 import net.minecraft.world.level.block.state.BlockState;
 import net.minecraft.world.level.gameevent.GameEvent;
 import net.minecraft.world.phys.Vec3;
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+// CraftBukkit end
 
 public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackMob {
+
     private static final EntityDataAccessor<Byte> DATA_PUMPKIN_ID = SynchedEntityData.defineId(SnowGolem.class, EntityDataSerializers.BYTE);
     private static final byte PUMPKIN_FLAG = 16;
 
@@ -48,21 +54,23 @@
 
     @Override
     protected void registerGoals() {
-        this.goalSelector.addGoal(1, new RangedAttackGoal(this, 1.25, 20, 10.0F));
-        this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0, 1.0000001E-5F));
+        this.goalSelector.addGoal(1, new RangedAttackGoal(this, 1.25D, 20, 10.0F));
+        this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0D, 1.0000001E-5F));
         this.goalSelector.addGoal(3, new LookAtPlayerGoal(this, Player.class, 6.0F));
         this.goalSelector.addGoal(4, new RandomLookAroundGoal(this));
-        this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Mob.class, 10, true, false, entity -> entity instanceof Enemy));
+        this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Mob.class, 10, true, false, (entityliving) -> {
+            return entityliving instanceof Enemy;
+        }));
     }
 
     public static AttributeSupplier.Builder createAttributes() {
-        return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 4.0).add(Attributes.MOVEMENT_SPEED, 0.2F);
+        return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 4.0D).add(Attributes.MOVEMENT_SPEED, 0.20000000298023224D);
     }
 
     @Override
     protected void defineSynchedData(SynchedEntityData.Builder builder) {
         super.defineSynchedData(builder);
-        builder.define(DATA_PUMPKIN_ID, (byte)16);
+        builder.define(SnowGolem.DATA_PUMPKIN_ID, (byte) 16);
     }
 
     @Override
@@ -77,6 +85,7 @@
         if (nbt.contains("Pumpkin")) {
             this.setPumpkin(nbt.getBoolean("Pumpkin"));
         }
+
     }
 
     @Override
@@ -89,49 +98,69 @@
         super.aiStep();
         if (!this.level().isClientSide) {
             if (this.level().getBiome(this.blockPosition()).is(BiomeTags.SNOW_GOLEM_MELTS)) {
-                this.hurt(this.damageSources().onFire(), 1.0F);
+                this.hurt(this.damageSources().melting(), 1.0F); // CraftBukkit - DamageSources.ON_FIRE -> CraftEventFactory.MELTING
             }
 
             if (!this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
                 return;
             }
 
-            BlockState blockState = Blocks.SNOW.defaultBlockState();
+            BlockState iblockdata = Blocks.SNOW.defaultBlockState();
 
-            for (int i = 0; i < 4; i++) {
-                int j = Mth.floor(this.getX() + (double)((float)(i % 2 * 2 - 1) * 0.25F));
+            for (int i = 0; i < 4; ++i) {
+                int j = Mth.floor(this.getX() + (double) ((float) (i % 2 * 2 - 1) * 0.25F));
                 int k = Mth.floor(this.getY());
-                int l = Mth.floor(this.getZ() + (double)((float)(i / 2 % 2 * 2 - 1) * 0.25F));
-                BlockPos blockPos = new BlockPos(j, k, l);
-                if (this.level().getBlockState(blockPos).isAir() && blockState.canSurvive(this.level(), blockPos)) {
-                    this.level().setBlockAndUpdate(blockPos, blockState);
-                    this.level().gameEvent(GameEvent.BLOCK_PLACE, blockPos, GameEvent.Context.of(this, blockState));
+                int l = Mth.floor(this.getZ() + (double) ((float) (i / 2 % 2 * 2 - 1) * 0.25F));
+                BlockPos blockposition = new BlockPos(j, k, l);
+
+                if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) {
+                    // CraftBukkit start
+                    if (!CraftEventFactory.handleBlockFormEvent(this.level(), blockposition, iblockdata, this)) {
+                        continue;
+                    }
+                    // CraftBukkit end
+                    this.level().gameEvent((Holder) GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(this, iblockdata));
                 }
             }
         }
+
     }
 
     @Override
     public void performRangedAttack(LivingEntity target, float pullProgress) {
-        Snowball snowball = new Snowball(this.level(), this);
-        double d = target.getEyeY() - 1.1F;
-        double e = target.getX() - this.getX();
-        double f = d - snowball.getY();
-        double g = target.getZ() - this.getZ();
-        double h = Math.sqrt(e * e + g * g) * 0.2F;
-        snowball.shoot(e, f + h, g, 1.6F, 12.0F);
+        Snowball entitysnowball = new Snowball(this.level(), this);
+        double d0 = target.getEyeY() - 1.100000023841858D;
+        double d1 = target.getX() - this.getX();
+        double d2 = d0 - entitysnowball.getY();
+        double d3 = target.getZ() - this.getZ();
+        double d4 = Math.sqrt(d1 * d1 + d3 * d3) * 0.20000000298023224D;
+
+        entitysnowball.shoot(d1, d2 + d4, d3, 1.6F, 12.0F);
         this.playSound(SoundEvents.SNOW_GOLEM_SHOOT, 1.0F, 0.4F / (this.getRandom().nextFloat() * 0.4F + 0.8F));
-        this.level().addFreshEntity(snowball);
+        this.level().addFreshEntity(entitysnowball);
     }
 
     @Override
     protected InteractionResult mobInteract(Player player, InteractionHand hand) {
-        ItemStack itemStack = player.getItemInHand(hand);
-        if (itemStack.is(Items.SHEARS) && this.readyForShearing()) {
-            this.shear(SoundSource.PLAYERS);
+        ItemStack itemstack = player.getItemInHand(hand);
+
+        if (itemstack.is(Items.SHEARS) && this.readyForShearing()) {
+            // CraftBukkit start
+            // Paper start - custom shear drops
+            java.util.List<ItemStack> drops = this.generateDefaultDrops();
+            org.bukkit.event.player.PlayerShearEntityEvent event = CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops);
+            if (event != null) {
+                if (event.isCancelled()) {
+                    return InteractionResult.PASS;
+                }
+                drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops());
+            }
+            // Paper end - custom shear drops
+            // CraftBukkit end
+            this.shear(SoundSource.PLAYERS, drops); // Paper
             this.gameEvent(GameEvent.SHEAR, player);
             if (!this.level().isClientSide) {
-                itemStack.hurtAndBreak(1, player, getSlotForHand(hand));
+                itemstack.hurtAndBreak(1, player, getSlotForHand(hand));
             }
 
             return InteractionResult.sidedSuccess(this.level().isClientSide);
@@ -142,11 +171,30 @@
 
     @Override
     public void shear(SoundSource shearedSoundCategory) {
-        this.level().playSound(null, this, SoundEvents.SNOW_GOLEM_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
+        // Paper start - custom shear drops
+        this.shear(shearedSoundCategory, this.generateDefaultDrops());
+    }
+
+    @Override
+    public java.util.List<ItemStack> generateDefaultDrops() {
+        return java.util.Collections.singletonList(new ItemStack(Items.CARVED_PUMPKIN));
+    }
+
+    @Override
+    public void shear(SoundSource shearedSoundCategory, java.util.List<ItemStack> drops) {
+        // Paper end - custom shear drops
+        this.level().playSound((Player) null, (Entity) this, SoundEvents.SNOW_GOLEM_SHEAR, shearedSoundCategory, 1.0F, 1.0F);
         if (!this.level().isClientSide()) {
             this.setPumpkin(false);
-            this.spawnAtLocation(new ItemStack(Items.CARVED_PUMPKIN), this.getEyeHeight());
+            // Paper start - custom shear drops (moved drop generation to separate method)
+            for (final ItemStack drop : drops) {
+                this.forceDrops = true;
+                this.spawnAtLocation(drop, this.getEyeHeight());
+                this.forceDrops = false;
+            }
+            // Paper end - custom shear drops
         }
+
     }
 
     @Override
@@ -155,16 +203,18 @@
     }
 
     public boolean hasPumpkin() {
-        return (this.entityData.get(DATA_PUMPKIN_ID) & 16) != 0;
+        return ((Byte) this.entityData.get(SnowGolem.DATA_PUMPKIN_ID) & 16) != 0;
     }
 
     public void setPumpkin(boolean hasPumpkin) {
-        byte b = this.entityData.get(DATA_PUMPKIN_ID);
+        byte b0 = (Byte) this.entityData.get(SnowGolem.DATA_PUMPKIN_ID);
+
         if (hasPumpkin) {
-            this.entityData.set(DATA_PUMPKIN_ID, (byte)(b | 16));
+            this.entityData.set(SnowGolem.DATA_PUMPKIN_ID, (byte) (b0 | 16));
         } else {
-            this.entityData.set(DATA_PUMPKIN_ID, (byte)(b & -17));
+            this.entityData.set(SnowGolem.DATA_PUMPKIN_ID, (byte) (b0 & -17));
         }
+
     }
 
     @Nullable
@@ -187,6 +237,6 @@
 
     @Override
     public Vec3 getLeashOffset() {
-        return new Vec3(0.0, (double)(0.75F * this.getEyeHeight()), (double)(this.getBbWidth() * 0.4F));
+        return new Vec3(0.0D, (double) (0.75F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F));
     }
 }
