Skip to content

Commit

Permalink
Simplify shear patches and fix some differences compared to vanilla (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
pupnewfster authored Jan 30, 2024
1 parent f1652ec commit e21619f
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 144 deletions.
5 changes: 3 additions & 2 deletions patches/net/minecraft/world/entity/Entity.java.patch
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@
public void setMaxUpStep(float p_275672_) {
this.maxUpStep = p_275672_;
}
@@ -3419,6 +_,119 @@
@@ -3419,6 +_,120 @@
public boolean mayInteract(Level p_146843_, BlockPos p_146844_) {
return true;
}
Expand All @@ -548,13 +548,14 @@
+ public boolean canUpdate() {
+ return this.canUpdate;
+ }
+ @Nullable
+ private java.util.Collection<ItemEntity> captureDrops = null;
+ @Override
+ public java.util.Collection<ItemEntity> captureDrops() {
+ return captureDrops;
+ }
+ @Override
+ public java.util.Collection<ItemEntity> captureDrops(java.util.Collection<ItemEntity> value) {
+ public java.util.Collection<ItemEntity> captureDrops(@Nullable java.util.Collection<ItemEntity> value) {
+ java.util.Collection<ItemEntity> ret = captureDrops;
+ this.captureDrops = value;
+ return ret;
Expand Down
20 changes: 15 additions & 5 deletions patches/net/minecraft/world/entity/Shearable.java.patch
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
--- a/net/minecraft/world/entity/Shearable.java
+++ b/net/minecraft/world/entity/Shearable.java
@@ -2,8 +_,11 @@
@@ -2,8 +_,20 @@

import net.minecraft.sounds.SoundSource;

+@Deprecated // Forge: Use IShearable
public interface Shearable {
+ @Deprecated // Forge: Use IShearable
-public interface Shearable {
+/**
+ * @deprecated Neo: Use {@link net.neoforged.neoforge.common.IShearable} instead.
+ */
+@Deprecated
+public interface Shearable extends net.neoforged.neoforge.common.IShearable {
+ /**
+ * @deprecated Neo: Use {@link net.neoforged.neoforge.common.IShearable#onSheared(net.minecraft.world.entity.player.Player, net.minecraft.world.item.ItemStack, net.minecraft.world.level.Level, net.minecraft.core.BlockPos, int)} instead.
+ */
+ @Deprecated
void shear(SoundSource p_21749_);

+ @Deprecated // Forge: Use IShearable
+ /**
+ * @deprecated Neo: Use {@link net.neoforged.neoforge.common.IShearable#isShearable(net.minecraft.world.item.ItemStack, net.minecraft.world.level.Level, net.minecraft.core.BlockPos)} instead.
+ */
+ @Deprecated
boolean readyForShearing();
}
50 changes: 6 additions & 44 deletions patches/net/minecraft/world/entity/animal/MushroomCow.java.patch
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
--- a/net/minecraft/world/entity/animal/MushroomCow.java
+++ b/net/minecraft/world/entity/animal/MushroomCow.java
@@ -42,7 +_,7 @@
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.gameevent.GameEvent;

-public class MushroomCow extends Cow implements Shearable, VariantHolder<MushroomCow.MushroomType> {
+public class MushroomCow extends Cow implements Shearable, net.neoforged.neoforge.common.IShearable {
private static final EntityDataAccessor<String> DATA_TYPE = SynchedEntityData.defineId(MushroomCow.class, EntityDataSerializers.STRING);
private static final int MUTATE_CHANCE = 1024;
private static final String TAG_STEW_EFFECTS = "stew_effects";
@@ -108,7 +_,7 @@

this.playSound(soundevent, 1.0F, 1.0F);
Expand All @@ -18,57 +9,28 @@
this.shear(SoundSource.PLAYERS);
this.gameEvent(GameEvent.SHEAR, p_28941_);
if (!this.level().isClientSide) {
@@ -164,11 +_,22 @@
}

@Override
+ public java.util.List<ItemStack> onSheared(@org.jetbrains.annotations.Nullable Player player, @org.jetbrains.annotations.NotNull ItemStack item, Level world, BlockPos pos, int fortune) {
+ this.gameEvent(GameEvent.SHEAR, player);
+ return shearInternal(player == null ? SoundSource.BLOCKS : SoundSource.PLAYERS);
+ }
+
@@ -167,8 +_,10 @@
public void shear(SoundSource p_28924_) {
+ shearInternal(p_28924_).forEach(s -> this.level().addFreshEntity(new ItemEntity(this.level(), this.getX(), this.getY(1.0D), this.getZ(), s)));
+ }
+
+ private java.util.List<ItemStack> shearInternal(SoundSource p_28924_) {
this.level().playSound(null, this, SoundEvents.MOOSHROOM_SHEAR, p_28924_, 1.0F, 1.0F);
if (!this.level().isClientSide()) {
+ if (!net.neoforged.neoforge.event.EventHooks.canLivingConvert(this, EntityType.COW, (timer) -> {})) return java.util.Collections.emptyList();
+ if (!net.neoforged.neoforge.event.EventHooks.canLivingConvert(this, EntityType.COW, (timer) -> {})) return;
Cow cow = EntityType.COW.create(this.level());
if (cow != null) {
+ net.neoforged.neoforge.event.EventHooks.onLivingConvert(this, cow);
((ServerLevel)this.level()).sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(0.5), this.getZ(), 1, 0.0, 0.0, 0.0, 0.0);
this.discard();
cow.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot());
@@ -186,14 +_,14 @@
cow.setInvulnerable(this.isInvulnerable());
@@ -187,10 +_,9 @@
this.level().addFreshEntity(cow);

+ java.util.List<ItemStack> items = new java.util.ArrayList<>();
for(int i = 0; i < 5; ++i) {
- this.level()
- .addFreshEntity(
- new ItemEntity(this.level(), this.getX(), this.getY(1.0), this.getZ(), new ItemStack(this.getVariant().blockState.getBlock()))
- );
+ items.add(new ItemStack(this.getVariant().blockState.getBlock()));
+ //Neo: Change from addFreshEntity to spawnAtLocation to ensure captureDrops can capture this, we also need to unset the default pickup delay from the item
+ ItemEntity item = spawnAtLocation(new ItemStack(this.getVariant().blockState.getBlock()), getBbHeight());
+ if (item != null) item.setNoPickUpDelay();
}
+ return items;
}
}
+ return java.util.Collections.emptyList();
}

@Override
@@ -261,6 +_,11 @@
}

return mushroomcow$mushroomtype2;
+ }
+
+ @Override
+ public boolean isShearable(@org.jetbrains.annotations.NotNull ItemStack item, Level world, BlockPos pos) {
+ return readyForShearing();
}

public static enum MushroomType implements StringRepresentable {
39 changes: 0 additions & 39 deletions patches/net/minecraft/world/entity/animal/Sheep.java.patch
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
--- a/net/minecraft/world/entity/animal/Sheep.java
+++ b/net/minecraft/world/entity/animal/Sheep.java
@@ -65,7 +_,7 @@
import net.minecraft.world.level.storage.loot.BuiltInLootTables;
import org.joml.Vector3f;

-public class Sheep extends Animal implements Shearable {
+public class Sheep extends Animal implements Shearable, net.neoforged.neoforge.common.IShearable {
private static final int EAT_ANIMATION_TICKS = 40;
private static final EntityDataAccessor<Byte> DATA_WOOL_ID = SynchedEntityData.defineId(Sheep.class, EntityDataSerializers.BYTE);
private static final Map<DyeColor, ItemLike> ITEM_BY_DYE = Util.make(Maps.newEnumMap(DyeColor.class), p_29841_ -> {
@@ -206,7 +_,7 @@
@Override
public InteractionResult mobInteract(Player p_29853_, InteractionHand p_29854_) {
Expand All @@ -18,33 +9,3 @@
if (!this.level().isClientSide && this.readyForShearing()) {
this.shear(SoundSource.PLAYERS);
this.gameEvent(GameEvent.SHEAR, p_29853_);
@@ -380,6 +_,29 @@
@Override
protected float getStandingEyeHeight(Pose p_29850_, EntityDimensions p_29851_) {
return 0.95F * p_29851_.height;
+ }
+
+ @Override
+ public boolean isShearable(@org.jetbrains.annotations.NotNull ItemStack item, Level world, BlockPos pos) {
+ return readyForShearing();
+ }
+
+ @org.jetbrains.annotations.NotNull
+ @Override
+ public java.util.List<ItemStack> onSheared(@Nullable Player player, @org.jetbrains.annotations.NotNull ItemStack item, Level world, BlockPos pos, int fortune) {
+ world.playSound(null, this, SoundEvents.SHEEP_SHEAR, player == null ? SoundSource.BLOCKS : SoundSource.PLAYERS, 1.0F, 1.0F);
+ this.gameEvent(GameEvent.SHEAR, player);
+ if (!world.isClientSide) {
+ this.setSheared(true);
+ int i = 1 + this.random.nextInt(3);
+
+ java.util.List<ItemStack> items = new java.util.ArrayList<>();
+ for (int j = 0; j < i; ++j) {
+ items.add(new ItemStack(ITEM_BY_DYE.get(this.getColor())));
+ }
+ return items;
+ }
+ return java.util.Collections.emptyList();
}

@Override
32 changes: 0 additions & 32 deletions patches/net/minecraft/world/entity/animal/SnowGolem.java.patch
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
--- a/net/minecraft/world/entity/animal/SnowGolem.java
+++ b/net/minecraft/world/entity/animal/SnowGolem.java
@@ -40,7 +_,7 @@
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.phys.Vec3;

-public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackMob {
+public class SnowGolem extends AbstractGolem implements Shearable, RangedAttackMob, net.neoforged.neoforge.common.IShearable {
private static final EntityDataAccessor<Byte> DATA_PUMPKIN_ID = SynchedEntityData.defineId(SnowGolem.class, EntityDataSerializers.BYTE);
private static final byte PUMPKIN_FLAG = 16;
private static final float EYE_HEIGHT = 1.7F;
@@ -95,7 +_,7 @@
this.hurt(this.damageSources().onFire(), 1.0F);
}
Expand All @@ -27,26 +18,3 @@
this.shear(SoundSource.PLAYERS);
this.gameEvent(GameEvent.SHEAR, p_29920_);
if (!this.level().isClientSide) {
@@ -196,5 +_,22 @@
@Override
public Vec3 getLeashOffset() {
return new Vec3(0.0, (double)(0.75F * this.getEyeHeight()), (double)(this.getBbWidth() * 0.4F));
+ }
+
+ @Override
+ public boolean isShearable(@org.jetbrains.annotations.NotNull ItemStack item, Level world, BlockPos pos) {
+ return readyForShearing();
+ }
+
+ @org.jetbrains.annotations.NotNull
+ @Override
+ public java.util.List<ItemStack> onSheared(@Nullable Player player, @org.jetbrains.annotations.NotNull ItemStack item, Level world, BlockPos pos, int fortune) {
+ world.playSound(null, this, SoundEvents.SNOW_GOLEM_SHEAR, player == null ? SoundSource.BLOCKS : SoundSource.PLAYERS, 1.0F, 1.0F);
+ this.gameEvent(GameEvent.SHEAR, player);
+ if (!world.isClientSide()) {
+ setPumpkin(false);
+ return java.util.Collections.singletonList(new ItemStack(Items.CARVED_PUMPKIN));
+ }
+ return java.util.Collections.emptyList();
}
}
24 changes: 10 additions & 14 deletions patches/net/minecraft/world/item/ShearsItem.java.patch
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
--- a/net/minecraft/world/item/ShearsItem.java
+++ b/net/minecraft/world/item/ShearsItem.java
@@ -59,6 +_,31 @@
@@ -59,6 +_,27 @@
}

@Override
+ public net.minecraft.world.InteractionResult interactLivingEntity(ItemStack stack, net.minecraft.world.entity.player.Player playerIn, LivingEntity entity, net.minecraft.world.InteractionHand hand) {
+ public InteractionResult interactLivingEntity(ItemStack stack, Player player, LivingEntity entity, net.minecraft.world.InteractionHand hand) {
+ if (entity instanceof net.neoforged.neoforge.common.IShearable target) {
+ if (entity.level().isClientSide) return net.minecraft.world.InteractionResult.SUCCESS;
+ BlockPos pos = BlockPos.containing(entity.position());
+ if (entity.level().isClientSide) return InteractionResult.CONSUME;
+ BlockPos pos = entity.blockPosition();
+ if (target.isShearable(stack, entity.level(), pos)) {
+ java.util.List<ItemStack> drops = target.onSheared(playerIn, stack, entity.level(), pos,
+ net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.BLOCK_FORTUNE, stack));
+ java.util.Random rand = new java.util.Random();
+ drops.forEach(d -> {
+ net.minecraft.world.entity.item.ItemEntity ent = entity.spawnAtLocation(d, 1.0F);
+ ent.setDeltaMovement(ent.getDeltaMovement().add((double)((rand.nextFloat() - rand.nextFloat()) * 0.1F), (double)(rand.nextFloat() * 0.05F), (double)((rand.nextFloat() - rand.nextFloat()) * 0.1F)));
+ });
+ stack.hurtAndBreak(1, playerIn, e -> e.broadcastBreakEvent(hand));
+ target.onSheared(player, stack, entity.level(), pos, stack.getEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.BLOCK_FORTUNE))
+ .forEach(drop -> target.spawnShearedDrop(entity.level(), pos, drop));
+ entity.gameEvent(GameEvent.SHEAR, player);
+ stack.hurtAndBreak(1, player, e -> e.broadcastBreakEvent(hand));
+ }
+ return net.minecraft.world.InteractionResult.SUCCESS;
+ return InteractionResult.SUCCESS;
+ }
+ return net.minecraft.world.InteractionResult.PASS;
+ return InteractionResult.PASS;
+ }
+
+ @Override
Expand Down
57 changes: 49 additions & 8 deletions src/main/java/net/neoforged/neoforge/common/IShearable.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@

package net.neoforged.neoforge.common;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.minecraft.core.BlockPos;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Shearable;
import net.minecraft.world.entity.animal.MushroomCow;
import net.minecraft.world.entity.animal.SnowGolem;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
Expand All @@ -33,7 +40,7 @@ public interface IShearable {
* @return If this is shearable, and onSheared should be called.
*/
default boolean isShearable(ItemStack item, Level level, BlockPos pos) {
return true;
return !(this instanceof Shearable shearable) || shearable.readyForShearing();
}

/**
Expand All @@ -42,20 +49,54 @@ default boolean isShearable(ItemStack item, Level level, BlockPos pos) {
* The object should perform all actions related to being sheared,
* except for dropping of the items, and removal of the block.
* As those are handled by ItemShears itself.
*
* Returns a list of items that resulted from the shearing process.
*
* For entities, they should trust there internal location information
* over the values passed into this function.
* <p>
* For entities, they should trust their internal location information over the values passed into this function.
*
* @param item The ItemStack that is being used, may be empty.
* @param level The current level.
* @param pos If this is a block, the block's position in level.
* @param fortune The fortune level of the shears being used.
* @return A List containing all items from this shearing. May be empty.
* @return A List containing all items that resulted from the shearing process. May be empty.
*/

default List<ItemStack> onSheared(@Nullable Player player, ItemStack item, Level level, BlockPos pos, int fortune) {
if (this instanceof LivingEntity entity && this instanceof Shearable shearable) {
if (!level.isClientSide) {
List<ItemEntity> drops = new ArrayList<>();
entity.captureDrops(drops);
shearable.shear(player == null ? SoundSource.BLOCKS : SoundSource.PLAYERS);
return entity.captureDrops(null).stream().map(ItemEntity::getItem).toList();
}
}
return Collections.emptyList();
}

/**
* Performs the logic used to drop a shear result into the world at the correct position and with the proper movement.
* <br>
* For entities, they should trust their internal location information over the values passed into this function.
*
* @param level The current level.
* @param pos If this is a block, the block's position in level.
* @param drop The ItemStack to drop.
*/
default void spawnShearedDrop(Level level, BlockPos pos, ItemStack drop) {
if (this instanceof SnowGolem golem) {
golem.spawnAtLocation(drop, 1.7F);
} else if (this instanceof MushroomCow cow) {
// Note: Vanilla uses addFreshEntity instead of spawnAtLocation for spawning mooshrooms drops
// In case a mod is capturing drops for the entity we instead do it the same way we patch in MushroomCow#shear
ItemEntity itemEntity = cow.spawnAtLocation(drop, cow.getBbHeight());
if (itemEntity != null) itemEntity.setNoPickUpDelay();
} else if (this instanceof LivingEntity entity) {
ItemEntity itemEntity = entity.spawnAtLocation(drop, 1);
if (itemEntity != null) {
itemEntity.setDeltaMovement(itemEntity.getDeltaMovement().add(
((entity.getRandom().nextFloat() - entity.getRandom().nextFloat()) * 0.1F),
(entity.getRandom().nextFloat() * 0.05F),
((entity.getRandom().nextFloat() - entity.getRandom().nextFloat()) * 0.1F)));
}
} else {
level.addFreshEntity(new ItemEntity(level, pos.getX(), pos.getY(), pos.getZ(), drop));
}
}
}

0 comments on commit e21619f

Please sign in to comment.