mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-14 01:04:24 +00:00
Remove IForgeShearable Closes #10826
Entities use vanilla's Shearable interface Blocks use loot table conditions or useItemOn if you need positional information
This commit is contained in:
25 files changed
+186
-424
No files matched your search
@@ -33,6 +33,7 @@
|
||||
/projects/**/run/
|
||||
/projects/**/*.launch
|
||||
/repo/
|
||||
/rejects-*/
|
||||
src/*/generated/**/.cache/
|
||||
|
||||
# Generated by gradle every import
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
--- a/net/minecraft/world/entity/Shearable.java
|
||||
+++ b/net/minecraft/world/entity/Shearable.java
|
||||
@@ -4,8 +_,14 @@
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
-public interface Shearable {
|
||||
+public interface Shearable extends net.minecraftforge.common.IForgeShearable {
|
||||
+ /** @deprecated Use {@link net.minecraftforge.common.IForgeShearable#onSheared} */
|
||||
@@ -8,4 +_,17 @@
|
||||
void shear(ServerLevel level, SoundSource soundSource, ItemStack tool);
|
||||
|
||||
+ /** @deprecated Use {@link net.minecraftforge.common.IForgeShearable#isShearable} */
|
||||
boolean readyForShearing();
|
||||
+
|
||||
+ default boolean isShearable(net.minecraft.world.item.ItemStack item, net.minecraft.world.level.Level level, net.minecraft.core.BlockPos pos) {
|
||||
+ return readyForShearing();
|
||||
+ /** Equivalent to {@link shear} but returns a list of ItemStacks without actually spawning the entity into the world */
|
||||
+ default java.util.List<ItemStack> shearItems(ServerLevel level, SoundSource soundSource, ItemStack tool) {
|
||||
+ var self = (Entity)this;
|
||||
+ var entities = new java.util.ArrayList<net.minecraft.world.entity.item.ItemEntity>();
|
||||
+ self.captureDrops(entities);
|
||||
+ shear(level, soundSource, tool);
|
||||
+ self.captureDrops(null);
|
||||
+ var items = new java.util.ArrayList<ItemStack>(entities.size());
|
||||
+ for (var entity : entities)
|
||||
+ items.add(entity.getItem());
|
||||
+ return items;
|
||||
+ }
|
||||
}
|
||||
@@ -5,53 +5,24 @@
|
||||
this.playSound(milkSound, 1.0F, 1.0F);
|
||||
return InteractionResult.SUCCESS;
|
||||
- } else if (itemStack.is(Items.SHEARS) && this.readyForShearing()) {
|
||||
+ } else if (false && itemStack.is(Items.SHEARS) && this.readyForShearing()) {
|
||||
+ } else if (itemStack.canPerformAction(net.minecraftforge.common.ToolActions.SHEARS_HARVEST) && this.readyForShearing()) {
|
||||
if (this.level() instanceof ServerLevel level) {
|
||||
this.shear(level, SoundSource.PLAYERS, itemStack);
|
||||
this.gameEvent(GameEvent.SHEAR, player);
|
||||
@@ -178,15 +_,26 @@
|
||||
@@ -178,6 +_,8 @@
|
||||
|
||||
@Override
|
||||
public void shear(final ServerLevel level, final SoundSource soundSource, final ItemStack tool) {
|
||||
+ for (var stack : shearInternal(level, soundSource, tool)) {
|
||||
+ for (int i = 0; i < stack.getCount(); i++) {
|
||||
+ this.level().addFreshEntity(new ItemEntity(this.level(), this.getX(), this.getY(1.0D), this.getZ(), stack.copyWithCount(1)));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private java.util.List<ItemStack> shearInternal(ServerLevel level, SoundSource soundSource, ItemStack tool) {
|
||||
+ var ret = new java.util.ArrayList<ItemStack>();
|
||||
+ if (!net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityTypes.COW, time -> {}))
|
||||
+ return ret;
|
||||
+ return;
|
||||
level.playSound(null, this, SoundEvents.MOOSHROOM_SHEAR, soundSource, 1.0F, 1.0F);
|
||||
this.convertTo(EntityTypes.COW, ConversionParams.single(this, false, false), cow -> {
|
||||
level.sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(0.5), this.getZ(), 1, 0.0, 0.0, 0.0, 0.0);
|
||||
this.dropFromShearingLootTable(level, BuiltInLootTables.SHEAR_MOOSHROOM, tool, (l, drop) -> {
|
||||
- for (int i = 0; i < drop.getCount(); i++) {
|
||||
- l.addFreshEntity(new ItemEntity(this.level(), this.getX(), this.getY(1.0), this.getZ(), drop.copyWithCount(1)));
|
||||
- }
|
||||
+ ret.add(tool);
|
||||
@@ -186,6 +_,7 @@
|
||||
l.addFreshEntity(new ItemEntity(this.level(), this.getX(), this.getY(1.0), this.getZ(), drop.copyWithCount(1)));
|
||||
}
|
||||
});
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, cow);
|
||||
});
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -267,6 +_,15 @@
|
||||
}
|
||||
|
||||
return babyVariant;
|
||||
+ }
|
||||
+
|
||||
+ @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) {
|
||||
+ if (world instanceof ServerLevel server) {
|
||||
+ this.gameEvent(GameEvent.SHEAR, player);
|
||||
+ return shearInternal(server, player == null ? SoundSource.BLOCKS : SoundSource.PLAYERS, item);
|
||||
+ }
|
||||
+ return java.util.Collections.emptyList();
|
||||
}
|
||||
|
||||
public enum Variant implements StringRepresentable {
|
||||
@@ -5,26 +5,7 @@
|
||||
|
||||
Level level = this.level();
|
||||
- if (itemStack.is(Items.SHEARS) && this.readyForShearing()) {
|
||||
+ if (false && itemStack.is(Items.SHEARS) && this.readyForShearing()) { // Forge: Moved to onSheared
|
||||
+ if (itemStack.canPerformAction(net.minecraftforge.common.ToolActions.SHEARS_HARVEST) && this.readyForShearing()) {
|
||||
if (level instanceof ServerLevel serverLevel) {
|
||||
this.shear(serverLevel, SoundSource.PLAYERS, itemStack);
|
||||
this.gameEvent(GameEvent.SHEAR, player);
|
||||
@@ -435,6 +_,18 @@
|
||||
ItemStack itemStack = this.getItemBySlot(EQUIPMENT_SLOT_ANTENNA);
|
||||
this.setItemSlot(EQUIPMENT_SLOT_ANTENNA, ItemStack.EMPTY);
|
||||
this.spawnAtLocation(level, itemStack, 1.5F);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<ItemStack> onSheared(@Nullable Player player, ItemStack item, Level world, net.minecraft.core.BlockPos pos, int fortune) {
|
||||
+ if (world instanceof ServerLevel server) {
|
||||
+ server.playSound(null, this, SoundEvents.COPPER_GOLEM_SHEAR, player == null ? SoundSource.BLOCKS : SoundSource.PLAYERS, 1.0F, 1.0F);
|
||||
+ var ret = new java.util.ArrayList<ItemStack>();
|
||||
+ ret.add(this.getItemBySlot(EQUIPMENT_SLOT_ANTENNA));
|
||||
+ this.setItemSlot(EQUIPMENT_SLOT_ANTENNA, ItemStack.EMPTY);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ return java.util.Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1,14 +1,5 @@
|
||||
--- a/net/minecraft/world/entity/animal/golem/SnowGolem.java
|
||||
+++ b/net/minecraft/world/entity/animal/golem/SnowGolem.java
|
||||
@@ -42,7 +_,7 @@
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
-public class SnowGolem extends AbstractGolem implements RangedAttackMob, Shearable {
|
||||
+public class SnowGolem extends AbstractGolem implements RangedAttackMob, Shearable, net.minecraftforge.common.IForgeShearable {
|
||||
private static final EntityDataAccessor<Byte> DATA_PUMPKIN_ID = SynchedEntityData.defineId(SnowGolem.class, EntityDataSerializers.BYTE);
|
||||
private static final byte PUMPKIN_FLAG = 16;
|
||||
private static final boolean DEFAULT_PUMPKIN = true;
|
||||
@@ -95,7 +_,7 @@
|
||||
this.hurtServer(serverLevel, this.damageSources().onFire(), 1.0F);
|
||||
}
|
||||
@@ -32,25 +23,7 @@
|
||||
protected InteractionResult mobInteract(final Player player, final InteractionHand hand) {
|
||||
ItemStack itemStack = player.getItemInHand(hand);
|
||||
- if (itemStack.is(Items.SHEARS) && this.readyForShearing()) {
|
||||
+ if (false && itemStack.is(Items.SHEARS) && this.readyForShearing()) { //Forge: Moved to onSheared
|
||||
+ if (itemStack.canPerformAction(net.minecraftforge.common.ToolActions.SHEARS_HARVEST) && this.readyForShearing()) {
|
||||
if (this.level() instanceof ServerLevel level) {
|
||||
this.shear(level, SoundSource.PLAYERS, itemStack);
|
||||
this.gameEvent(GameEvent.SHEAR, player);
|
||||
@@ -193,4 +_,17 @@
|
||||
public Vec3 getLeashOffset() {
|
||||
return new Vec3(0.0, 0.75F * this.getEyeHeight(), this.getBbWidth() * 0.4F);
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.@org.jspecify.annotations.NonNull List<ItemStack> onSheared(@Nullable Player player, @org.jspecify.annotations.NonNull 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() && world instanceof ServerLevel server) {
|
||||
+ setPumpkin(false);
|
||||
+ var ret = new java.util.ArrayList<ItemStack>();
|
||||
+ this.dropFromShearingLootTable(server, BuiltInLootTables.SHEAR_SNOW_GOLEM, item, (slevel, stack) -> ret.add(stack));
|
||||
+ return ret;
|
||||
+ }
|
||||
+ return java.util.Collections.emptyList();
|
||||
+ }
|
||||
}
|
||||
@@ -5,52 +5,7 @@
|
||||
public InteractionResult mobInteract(final Player player, final InteractionHand hand) {
|
||||
ItemStack itemStack = player.getItemInHand(hand);
|
||||
- if (itemStack.is(Items.SHEARS)) {
|
||||
+ if (false && itemStack.is(Items.SHEARS)) { // Forge: Moved to onSheared
|
||||
+ if (itemStack.canPerformAction(net.minecraftforge.common.ToolActions.SHEARS_HARVEST)) {
|
||||
if (this.level() instanceof ServerLevel level && this.readyForShearing()) {
|
||||
this.shear(level, SoundSource.PLAYERS, itemStack);
|
||||
this.gameEvent(GameEvent.SHEAR, player);
|
||||
@@ -161,12 +_,27 @@
|
||||
|
||||
@Override
|
||||
public void shear(final ServerLevel level, final SoundSource soundSource, final ItemStack tool) {
|
||||
+ dropItems(level, shearInternal(level, soundSource, tool));
|
||||
+ }
|
||||
+
|
||||
+ private java.util.List<ItemStack> shearInternal(ServerLevel level, SoundSource soundSource, ItemStack tool) {
|
||||
+ var ret = new java.util.ArrayList<ItemStack>();
|
||||
level.playSound(null, this, SoundEvents.SHEEP_SHEAR, soundSource, 1.0F, 1.0F);
|
||||
this.dropFromShearingLootTable(
|
||||
level,
|
||||
BuiltInLootTables.SHEAR_SHEEP,
|
||||
tool,
|
||||
(l, drop) -> {
|
||||
+ ret.add(drop);
|
||||
+ }
|
||||
+ );
|
||||
+ this.setSheared(true);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ private void dropItems(ServerLevel l, java.util.Collection<ItemStack> items) {
|
||||
+ // double indented to make the patch look nicer
|
||||
+ for (var drop : items) {
|
||||
for (int i = 0; i < drop.getCount(); i++) {
|
||||
ItemEntity entity = this.spawnAtLocation(l, drop.copyWithCount(1), 1.0F);
|
||||
if (entity != null) {
|
||||
@@ -181,8 +_,14 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
- );
|
||||
- this.setSheared(true);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<ItemStack> onSheared(@Nullable Player player, ItemStack item, Level level, BlockPos pos, int fortune) {
|
||||
+ if (level instanceof ServerLevel server) {
|
||||
+ return shearInternal(server, player == null ? SoundSource.BLOCKS : SoundSource.PLAYERS, item);
|
||||
+ }
|
||||
+ return java.util.Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -11,3 +11,12 @@
|
||||
if (this.hasBodyItem() && this.floatsInLiquids) {
|
||||
float vibeAmount = 0.2F * Mth.sin(this.tickCount * 0.4F);
|
||||
double immersion = this.getFluidHeight(this.isInWater() ? FluidTags.WATER : FluidTags.LAVA) - this.getFluidJumpThreshold() + vibeAmount;
|
||||
@@ -452,7 +_,7 @@
|
||||
}
|
||||
|
||||
if (!this.canExplode() || !heldItem.is(Items.FLINT_AND_STEEL) && !heldItem.is(Items.FIRE_CHARGE)) {
|
||||
- if (heldItem.is(Items.SHEARS) && this.readyForShearing()) {
|
||||
+ if (heldItem.canPerformAction(net.minecraftforge.common.ToolActions.SHEARS_HARVEST) && this.readyForShearing()) {
|
||||
if (this.level() instanceof ServerLevel level) {
|
||||
ItemStack itemStackToShear = this.getItemBySlot(EquipmentSlot.BODY);
|
||||
this.shear(level, SoundSource.PLAYERS, heldItem);
|
||||
@@ -5,25 +5,7 @@
|
||||
protected InteractionResult mobInteract(final Player player, final InteractionHand hand) {
|
||||
ItemStack itemStack = player.getItemInHand(hand);
|
||||
- if (itemStack.is(Items.SHEARS) && this.readyForShearing()) {
|
||||
+ if (false && itemStack.is(Items.SHEARS) && this.readyForShearing()) { // Forge: move to onSheared
|
||||
+ if (itemStack.canPerformAction(net.minecraftforge.common.ToolActions.SHEARS_HARVEST) && this.readyForShearing()) {
|
||||
if (this.level() instanceof ServerLevel level) {
|
||||
this.shear(level, SoundSource.PLAYERS, itemStack);
|
||||
this.gameEvent(GameEvent.SHEAR, player);
|
||||
@@ -137,5 +_,17 @@
|
||||
@Override
|
||||
public boolean readyForShearing() {
|
||||
return !this.isSheared();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<ItemStack> onSheared(@org.jetbrains.annotations.Nullable Player player, @org.jetbrains.annotations.NotNull ItemStack item, Level world, net.minecraft.core.BlockPos pos, int fortune) {
|
||||
+ if (world instanceof ServerLevel server) {
|
||||
+ server.playSound(null, this, SoundEvents.BOGGED_SHEAR, SoundSource.PLAYERS, 1.0F, 1.0F);
|
||||
+ this.setSheared(true);
|
||||
+ var ret = new java.util.ArrayList<ItemStack>();
|
||||
+ this.dropFromShearingLootTable(server, BuiltInLootTables.BOGGED_SHEAR, item, (slevel, stack) -> ret.add(stack));
|
||||
+ return ret;
|
||||
+ }
|
||||
+ return java.util.Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,20 @@
|
||||
--- a/net/minecraft/world/item/ShearsItem.java
|
||||
+++ b/net/minecraft/world/item/ShearsItem.java
|
||||
@@ -83,4 +_,34 @@
|
||||
@@ -83,4 +_,23 @@
|
||||
return super.useOn(context);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public InteractionResult interactLivingEntity(ItemStack stack, Player playerIn, LivingEntity entity, net.minecraft.world.InteractionHand hand) {
|
||||
+ if (entity instanceof net.minecraftforge.common.IForgeShearable target) {
|
||||
+ if (entity.level().isClientSide()) {
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ }
|
||||
+ if (entity instanceof net.minecraft.world.entity.Shearable target) {
|
||||
+ if (entity.level().isClientSide() || !target.readyForShearing())
|
||||
+ return InteractionResult.CONSUME;
|
||||
+ var serverLevel = (net.minecraft.server.level.ServerLevel)entity.level();
|
||||
+
|
||||
+ BlockPos pos = BlockPos.containing(entity.position());
|
||||
+ if (target.isShearable(stack, entity.level(), pos)) {
|
||||
+ var key = net.minecraft.world.item.enchantment.Enchantments.FORTUNE;
|
||||
+ var drops = target.onSheared(playerIn, stack, entity.level(), pos, net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(entity.level().holderLookup(key.registryKey()).getOrThrow(key), stack));
|
||||
+ var rand = new java.util.Random();
|
||||
+ for (var drop : drops) {
|
||||
+ var ent = entity.spawnAtLocation(serverLevel, drop, 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)));
|
||||
+ }
|
||||
+ if (!drops.isEmpty())
|
||||
+ stack.hurtAndBreak(1, playerIn, hand.asEquipmentSlot());
|
||||
+ }
|
||||
+ return InteractionResult.SUCCESS;
|
||||
+ target.shear(serverLevel, SoundSource.PLAYERS, stack);
|
||||
+ serverLevel.gameEvent(playerIn, GameEvent.SHEAR, entity.position());
|
||||
+ stack.hurtAndBreak(1, playerIn, hand.asEquipmentSlot());
|
||||
+ return InteractionResult.SUCCESS_SERVER;
|
||||
+ }
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/net/minecraft/world/level/block/DryVegetationBlock.java
|
||||
+++ b/net/minecraft/world/level/block/DryVegetationBlock.java
|
||||
@@ -12,7 +_,7 @@
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
-public class DryVegetationBlock extends VegetationBlock {
|
||||
+public class DryVegetationBlock extends VegetationBlock implements net.minecraftforge.common.IForgeShearable {
|
||||
public static final MapCodec<DryVegetationBlock> CODEC = simpleCodec(DryVegetationBlock::new);
|
||||
private static final VoxelShape SHAPE = Block.column(12.0, 0.0, 13.0);
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/net/minecraft/world/level/block/LeavesBlock.java
|
||||
+++ b/net/minecraft/world/level/block/LeavesBlock.java
|
||||
@@ -26,7 +_,7 @@
|
||||
import net.minecraft.world.phys.shapes.Shapes;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
-public abstract class LeavesBlock extends Block implements SimpleWaterloggedBlock {
|
||||
+public abstract class LeavesBlock extends Block implements SimpleWaterloggedBlock, net.minecraftforge.common.IForgeShearable {
|
||||
public static final int DECAY_DISTANCE = 7;
|
||||
public static final IntegerProperty DISTANCE = BlockStateProperties.DISTANCE;
|
||||
public static final BooleanProperty PERSISTENT = BlockStateProperties.PERSISTENT;
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/net/minecraft/world/level/block/SeagrassBlock.java
|
||||
+++ b/net/minecraft/world/level/block/SeagrassBlock.java
|
||||
@@ -24,7 +_,7 @@
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
-public class SeagrassBlock extends VegetationBlock implements BonemealableBlock, LiquidBlockContainer {
|
||||
+public class SeagrassBlock extends VegetationBlock implements BonemealableBlock, LiquidBlockContainer, net.minecraftforge.common.IForgeShearable {
|
||||
public static final MapCodec<SeagrassBlock> CODEC = simpleCodec(SeagrassBlock::new);
|
||||
private static final VoxelShape SHAPE = Block.column(12.0, 0.0, 12.0);
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/net/minecraft/world/level/block/TallGrassBlock.java
|
||||
+++ b/net/minecraft/world/level/block/TallGrassBlock.java
|
||||
@@ -12,7 +_,7 @@
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
-public class TallGrassBlock extends VegetationBlock implements BonemealableBlock {
|
||||
+public class TallGrassBlock extends VegetationBlock implements BonemealableBlock, net.minecraftforge.common.IForgeShearable {
|
||||
public static final MapCodec<TallGrassBlock> CODEC = simpleCodec(TallGrassBlock::new);
|
||||
private static final VoxelShape SHAPE = Block.column(12.0, 0.0, 13.0);
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
--- a/net/minecraft/world/level/block/VineBlock.java
|
||||
+++ b/net/minecraft/world/level/block/VineBlock.java
|
||||
@@ -23,7 +_,7 @@
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
-public class VineBlock extends Block {
|
||||
+public class VineBlock extends Block implements net.minecraftforge.common.IForgeShearable {
|
||||
public static final MapCodec<VineBlock> CODEC = simpleCodec(VineBlock::new);
|
||||
public static final BooleanProperty UP = PipeBlock.UP;
|
||||
public static final BooleanProperty NORTH = PipeBlock.NORTH;
|
||||
@@ -168,7 +_,7 @@
|
||||
@Override
|
||||
protected void randomTick(final BlockState state, final ServerLevel level, final BlockPos pos, final RandomSource random) {
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/net/minecraft/world/level/block/WebBlock.java
|
||||
+++ b/net/minecraft/world/level/block/WebBlock.java
|
||||
@@ -11,7 +_,7 @@
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
-public class WebBlock extends Block {
|
||||
+public class WebBlock extends Block implements net.minecraftforge.common.IForgeShearable {
|
||||
public static final MapCodec<WebBlock> CODEC = simpleCodec(WebBlock::new);
|
||||
|
||||
@Override
|
||||
@@ -1,24 +0,0 @@
|
||||
++++ REJECTED HUNK: 1
|
||||
@@ -324,15 +324,18 @@
|
||||
}
|
||||
|
||||
public static ModelLayerLocation createStandingSignModelName(final WoodType type) {
|
||||
- return createLocation("sign/standing/" + type.name(), "main");
|
||||
+ Identifier location = Identifier.parse(type.name());
|
||||
+ return new ModelLayerLocation(Identifier.fromNamespaceAndPath(location.getNamespace(), "sign/standing/" + location.getPath()), "main");
|
||||
}
|
||||
|
||||
public static ModelLayerLocation createWallSignModelName(final WoodType type) {
|
||||
- return createLocation("sign/wall/" + type.name(), "main");
|
||||
+ Identifier location = Identifier.parse(type.name());
|
||||
+ return new ModelLayerLocation(Identifier.fromNamespaceAndPath(location.getNamespace(), "sign/wall/" + location.getPath()), "main");
|
||||
}
|
||||
|
||||
public static ModelLayerLocation createHangingSignModelName(final WoodType type, final HangingSignBlock.Attachment attachmentType) {
|
||||
- return createLocation("hanging_sign/" + type.name() + "/" + attachmentType.getSerializedName(), "main");
|
||||
+ Identifier location = Identifier.parse(type.name());
|
||||
+ return new ModelLayerLocation(Identifier.fromNamespaceAndPath(location.getNamespace(), "hanging_sign/" + location.getPath() + "/" + attachmentType.getSerializedName()), "main");
|
||||
}
|
||||
|
||||
public static Stream<ModelLayerLocation> getKnownLocations() {
|
||||
++++ END HUNK
|
||||
@@ -1,12 +0,0 @@
|
||||
++++ Target missing
|
||||
--- a/net/minecraft/client/renderer/feature/BlockFeatureRenderer.java
|
||||
+++ b/net/minecraft/client/renderer/feature/BlockFeatureRenderer.java
|
||||
@@ -153,7 +153,7 @@
|
||||
this.random.setSeed(submit.seed());
|
||||
|
||||
try {
|
||||
- submit.model().collectParts(this.random, this.parts);
|
||||
+ submit.model().collectParts(this.random, this.parts, submit.data());
|
||||
|
||||
for (BlockStateModelPart part : this.parts) {
|
||||
putPartQuads(part, submit.pose(), this.quadInstance, NO_TINT, buffer, null);
|
||||
@@ -1,67 +0,0 @@
|
||||
--- a/net/minecraft/client/renderer/rendertype/RenderSetup.java
|
||||
+++ b/net/minecraft/client/renderer/rendertype/RenderSetup.java
|
||||
@@ -32,6 +_,7 @@
|
||||
final boolean sortOnUpload;
|
||||
final int bufferSize;
|
||||
final LayeringTransform layeringTransform;
|
||||
+ final Map<String, RenderSetup.TextureAndSampler> texturesWithSamplers;
|
||||
|
||||
private RenderSetup(
|
||||
final RenderPipeline pipeline,
|
||||
@@ -44,7 +_,8 @@
|
||||
final RenderSetup.OutlineProperty outlineProperty,
|
||||
final boolean affectsCrumbling,
|
||||
final boolean sortOnUpload,
|
||||
- final int bufferSize
|
||||
+ final int bufferSize,
|
||||
+ Map<String, RenderSetup.TextureAndSampler> texturesWithSamplers
|
||||
) {
|
||||
this.pipeline = pipeline;
|
||||
this.textures = textures;
|
||||
@@ -57,6 +_,7 @@
|
||||
this.affectsCrumbling = affectsCrumbling;
|
||||
this.sortOnUpload = sortOnUpload;
|
||||
this.bufferSize = bufferSize;
|
||||
+ this.texturesWithSamplers = texturesWithSamplers;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -115,6 +_,8 @@
|
||||
);
|
||||
}
|
||||
|
||||
+ result.putAll(this.texturesWithSamplers);
|
||||
+
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -150,6 +_,7 @@
|
||||
private int bufferSize = 1536;
|
||||
private RenderSetup.OutlineProperty outlineProperty = RenderSetup.OutlineProperty.NONE;
|
||||
private final Map<String, RenderSetup.TextureBinding> textures = new HashMap<>();
|
||||
+ private final Map<String, RenderSetup.TextureAndSampler> texturesWithSamplers = new HashMap<>();
|
||||
|
||||
private RenderSetupBuilder(final RenderPipeline pipeline) {
|
||||
this.pipeline = pipeline;
|
||||
@@ -165,6 +_,11 @@
|
||||
return this;
|
||||
}
|
||||
|
||||
+ public RenderSetup.RenderSetupBuilder withTexture(String name, GpuTextureView textureView, GpuSampler sampler) {
|
||||
+ this.texturesWithSamplers.put(name, new RenderSetup.TextureAndSampler(textureView, sampler));
|
||||
+ return this;
|
||||
+ }
|
||||
+
|
||||
public RenderSetup.RenderSetupBuilder useLightmap() {
|
||||
this.useLightmap = true;
|
||||
return this;
|
||||
@@ -222,7 +_,8 @@
|
||||
this.outlineProperty,
|
||||
this.affectsCrumbling,
|
||||
this.sortOnUpload,
|
||||
- this.bufferSize
|
||||
+ this.bufferSize,
|
||||
+ this.texturesWithSamplers
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
*
|
||||
* This allows for mods to create there own Shear-like items
|
||||
* and have them interact with Blocks/Entities without extra work.
|
||||
* Also, if your block/entity supports the Shears, this allows you
|
||||
* to support mod-shears as well.
|
||||
*
|
||||
*/
|
||||
public interface IForgeShearable {
|
||||
/**
|
||||
* Checks if the object is currently shearable
|
||||
* Example: Sheep return false when they have no wool
|
||||
*
|
||||
* @param item The ItemStack that is being used, may be empty.
|
||||
* @param level The current level.
|
||||
* @param pos Block's position in level.
|
||||
* @return If this is shearable, and onSheared should be called.
|
||||
*/
|
||||
default boolean isShearable(@NotNull ItemStack item, Level level, BlockPos pos) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the shear function on this object.
|
||||
* This is called for both client, and server.
|
||||
* 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.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
@NotNull
|
||||
default List<ItemStack> onSheared(@Nullable Player player, @NotNull ItemStack item, Level level, BlockPos pos, int fortune) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "minecraft:function",
|
||||
"environment": "minecraft:default",
|
||||
"function": "forge:shears_behavior/custom_shears_shear_bogged",
|
||||
"max_ticks": 100,
|
||||
"structure": "forge:empty3x3x3"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "minecraft:function",
|
||||
"environment": "minecraft:default",
|
||||
"function": "forge:shears_behavior/custom_shears_shear_mooshroom",
|
||||
"max_ticks": 100,
|
||||
"structure": "forge:empty3x3x3"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "minecraft:function",
|
||||
"environment": "minecraft:default",
|
||||
"function": "forge:shears_behavior/custom_shears_shear_sheep",
|
||||
"max_ticks": 100,
|
||||
"structure": "forge:empty3x3x3"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "minecraft:function",
|
||||
"environment": "minecraft:default",
|
||||
"function": "forge:shears_behavior/custom_shears_shear_snowgolem",
|
||||
"max_ticks": 100,
|
||||
"structure": "forge:empty3x3x3"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"type": "minecraft:function",
|
||||
"environment": "minecraft:default",
|
||||
"function": "forge:shears_behavior/custom_shears_shear_sulfur_cube_block",
|
||||
"max_ticks": 100,
|
||||
"structure": "forge:empty3x3x3"
|
||||
}
|
||||
@@ -6,11 +6,16 @@
|
||||
package net.minecraftforge.debug.gameplay.item;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.gametest.framework.GameTestHelper;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityTypes;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.animal.cow.MushroomCow;
|
||||
import net.minecraft.world.entity.animal.golem.CopperGolem;
|
||||
import net.minecraft.world.entity.decoration.LeashFenceKnotEntity;
|
||||
import net.minecraft.world.item.DyeColor;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
@@ -48,6 +53,14 @@ public class ShearsBehaviorTest extends BaseTestMod {
|
||||
this.testItem(_ -> CUSTOM_SHEARS_HARVEST_ITEM.get().getDefaultInstance());
|
||||
}
|
||||
|
||||
private static void shear(GameTestHelper helper, Entity entity) {
|
||||
var player = helper.makeMockServerPlayer(GameType.SURVIVAL);
|
||||
var shears = CUSTOM_SHEARS_HARVEST_ITEM.get().getDefaultInstance();
|
||||
player.setItemInHand(InteractionHand.MAIN_HAND, shears);
|
||||
var result = player.interactOn(entity, InteractionHand.MAIN_HAND, Vec3.ZERO);
|
||||
helper.assertTrue(result.consumesAction(), "Using entity should result in consume action");
|
||||
}
|
||||
|
||||
@GameTest
|
||||
public static void custom_shears_unleash_entity(GameTestHelper helper) {
|
||||
helper.makeFloor();
|
||||
@@ -61,14 +74,9 @@ public class ShearsBehaviorTest extends BaseTestMod {
|
||||
cow.setLeashedTo(knot, true);
|
||||
helper.assertTrue(cow.isLeashed(), "Cow should start leashed");
|
||||
|
||||
// act: interact with cow using custom shears
|
||||
var player = helper.makeMockPlayer(GameType.SURVIVAL);
|
||||
var shears = CUSTOM_SHEARS_HARVEST_ITEM.get().getDefaultInstance();
|
||||
player.setItemInHand(InteractionHand.MAIN_HAND, shears);
|
||||
var result = player.interactOn(cow, InteractionHand.MAIN_HAND, Vec3.ZERO);
|
||||
shear(helper, cow);
|
||||
|
||||
// assert
|
||||
helper.assertTrue(result.consumesAction(), "Using custom shears on leashed cow should result in consume action");
|
||||
helper.assertTrue(!cow.isLeashed(), "Cow should be unleashed by custom shears");
|
||||
helper.assertItemEntityPresent(Items.LEAD);
|
||||
|
||||
@@ -89,14 +97,9 @@ public class ShearsBehaviorTest extends BaseTestMod {
|
||||
cow.setLeashedTo(knot, true);
|
||||
helper.assertTrue(cow.isLeashed(), "Cow should start leashed");
|
||||
|
||||
// act: interact with knot using custom shears
|
||||
var player = helper.makeMockPlayer(GameType.SURVIVAL);
|
||||
var shears = CUSTOM_SHEARS_HARVEST_ITEM.get().getDefaultInstance();
|
||||
player.setItemInHand(InteractionHand.MAIN_HAND, shears);
|
||||
var result = player.interactOn(knot, InteractionHand.MAIN_HAND, Vec3.ZERO);
|
||||
shear(helper, knot);
|
||||
|
||||
// assert
|
||||
helper.assertTrue(result.consumesAction(), "Using custom shears on leash knot should result in consume action");
|
||||
helper.assertTrue(!cow.isLeashed(), "Cow should be unleashed by sheared knot");
|
||||
helper.assertItemEntityPresent(Items.LEAD);
|
||||
|
||||
@@ -113,20 +116,110 @@ public class ShearsBehaviorTest extends BaseTestMod {
|
||||
golem.setItemSlot(CopperGolem.EQUIPMENT_SLOT_ANTENNA, new ItemStack(Items.POPPY));
|
||||
helper.assertTrue(golem.readyForShearing(), "Golem should start shearable (has poppy)");
|
||||
|
||||
// act: interact with copper golem using custom shears
|
||||
var player = helper.makeMockPlayer(GameType.SURVIVAL);
|
||||
var shears = CUSTOM_SHEARS_ITEM.get().getDefaultInstance();
|
||||
player.setItemInHand(InteractionHand.MAIN_HAND, shears);
|
||||
var result = player.interactOn(golem, InteractionHand.MAIN_HAND, Vec3.ZERO);
|
||||
shear(helper, golem);
|
||||
|
||||
// assert
|
||||
helper.assertTrue(result.consumesAction(), "Using custom shears on copper golem should result in consume action");
|
||||
helper.assertTrue(golem.getItemBySlot(CopperGolem.EQUIPMENT_SLOT_ANTENNA).isEmpty(), "Copper golem poppy should be sheared off with custom shears");
|
||||
helper.assertItemEntityPresent(Items.POPPY);
|
||||
|
||||
helper.succeed();
|
||||
}
|
||||
|
||||
@GameTest
|
||||
public static void custom_shears_shear_sulfur_cube_block(GameTestHelper helper) {
|
||||
helper.makeFloor();
|
||||
|
||||
// setup: sulfur cube with block
|
||||
var pos = new BlockPos(1, 1, 1);
|
||||
var sulfurCube = helper.spawnWithNoFreeWill(EntityTypes.SULFUR_CUBE, pos);
|
||||
sulfurCube.setItemSlot(EquipmentSlot.BODY, new ItemStack(Items.DIRT));
|
||||
helper.assertTrue(sulfurCube.readyForShearing(), "Sulfur cube should start shearable (has dirt block)");
|
||||
|
||||
shear(helper, sulfurCube);
|
||||
|
||||
// assert
|
||||
helper.assertTrue(sulfurCube.getItemBySlot(EquipmentSlot.BODY).isEmpty(), "Sulfur cube block should be sheared off with custom shears");
|
||||
helper.assertItemEntityPresent(Items.DIRT);
|
||||
|
||||
helper.succeed();
|
||||
}
|
||||
|
||||
@GameTest
|
||||
public static void custom_shears_shear_bogged(GameTestHelper helper) {
|
||||
helper.makeFloor();
|
||||
|
||||
var pos = new BlockPos(1, 1, 1);
|
||||
var entity = helper.spawnWithNoFreeWill(EntityTypes.BOGGED, pos);
|
||||
helper.assertTrue(entity.readyForShearing(), "Bogged start shearable");
|
||||
|
||||
shear(helper, entity);
|
||||
|
||||
// assert
|
||||
helper.assertTrue(!entity.readyForShearing(), "Bogged should no longer be shearable");
|
||||
int found = 0;
|
||||
for (var item : helper.getEntities(EntityTypes.ITEM, BlockPos.ZERO, 3)) {
|
||||
if (item.isAlive() && (item.getItem().is(Items.BROWN_MUSHROOM) || item.getItem().is(Items.RED_MUSHROOM)))
|
||||
found += item.getItem().count();
|
||||
}
|
||||
helper.assertValueEqual(found, 2, "Mushroom loot not found");
|
||||
|
||||
helper.succeed();
|
||||
}
|
||||
|
||||
@GameTest
|
||||
public static void custom_shears_shear_mooshroom(GameTestHelper helper) {
|
||||
helper.makeFloor();
|
||||
|
||||
var pos = new BlockPos(1, 1, 1);
|
||||
var entity = helper.spawnWithNoFreeWill(EntityTypes.MOOSHROOM, pos);
|
||||
entity.setComponent(DataComponents.MOOSHROOM_VARIANT, MushroomCow.Variant.RED);
|
||||
helper.assertTrue(entity.readyForShearing(), "Mooshroom start shearable");
|
||||
|
||||
shear(helper, entity);
|
||||
|
||||
// assert
|
||||
helper.assertTrue(!entity.isAlive(), "Mooshroom should no longer be alive");
|
||||
helper.assertEntityPresent(EntityTypes.COW);
|
||||
helper.assertItemEntityPresent(Items.RED_MUSHROOM);
|
||||
|
||||
helper.succeed();
|
||||
}
|
||||
|
||||
@GameTest
|
||||
public static void custom_shears_shear_sheep(GameTestHelper helper) {
|
||||
helper.makeFloor();
|
||||
|
||||
var pos = new BlockPos(1, 1, 1);
|
||||
var entity = helper.spawnWithNoFreeWill(EntityTypes.SHEEP, pos);
|
||||
entity.setColor(DyeColor.WHITE);
|
||||
helper.assertTrue(entity.readyForShearing(), "Sheep should start shearable");
|
||||
|
||||
shear(helper, entity);
|
||||
|
||||
// assert
|
||||
helper.assertTrue(!entity.readyForShearing(), "Sheep should no longer be shearable");
|
||||
helper.assertItemEntityPresent(Items.WOOL.white());
|
||||
|
||||
helper.succeed();
|
||||
}
|
||||
|
||||
@GameTest
|
||||
public static void custom_shears_shear_snowgolem(GameTestHelper helper) {
|
||||
helper.makeFloor();
|
||||
|
||||
var pos = new BlockPos(1, 1, 1);
|
||||
var entity = helper.spawnWithNoFreeWill(EntityTypes.SNOW_GOLEM, pos);
|
||||
helper.assertTrue(entity.readyForShearing(), "Snow golem should start shearable");
|
||||
|
||||
shear(helper, entity);
|
||||
|
||||
// assert
|
||||
helper.assertTrue(!entity.readyForShearing(), "Snow golem should no longer be shearable");
|
||||
helper.assertItemEntityPresent(Items.CARVED_PUMPKIN);
|
||||
|
||||
helper.succeed();
|
||||
}
|
||||
|
||||
private static final class ShearsHarvestItem extends Item {
|
||||
ShearsHarvestItem(Item.Properties properties) {
|
||||
super(properties);
|
||||
|
||||
Reference in new issue
Block a user