Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: granny <granny@purpurmc.org>
Date: Mon, 16 Oct 2023 21:54:47 -0700
Subject: [PATCH] config for turning bundles into functional quivers


diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 769acea46e91e07b711fbc6a92cfcad0564f5463..a99df447496225971a6be65a464e01f4f1cc6058 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -4824,6 +4824,11 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
}

public ItemStack getProjectile(final ItemStack heldWeapon) {
+ // Purpur start - config for turning bundles into functional quivers
+ return getProjectile(heldWeapon, false, false);
+ }
+ public ItemStack getProjectile(ItemStack heldWeapon, boolean useBundleComponentStack, boolean useBundleItemStack) {
+ // Purpur end - config for turning bundles into functional quivers
return ItemStack.EMPTY;
}

diff --git a/net/minecraft/world/entity/monster/Monster.java b/net/minecraft/world/entity/monster/Monster.java
index 81f1d4faebc38aa07a2c76c2c163584c8e5b624c..675b48168fd8c8ee06b67774440ff58d1c6b1b34 100644
--- a/net/minecraft/world/entity/monster/Monster.java
+++ b/net/minecraft/world/entity/monster/Monster.java
@@ -154,6 +154,12 @@ public abstract class Monster extends PathfinderMob implements Enemy {

@Override
public ItemStack getProjectile(final ItemStack heldWeapon) {
+ // Purpur start - config for turning bundles into functional quivers
+ return getProjectile(heldWeapon, false, false);
+ }
+ @Override
+ public ItemStack getProjectile(ItemStack heldWeapon, boolean useBundleComponentStack, boolean useBundleItemStack) {
+ // Purpur end - config for turning bundles into functional quivers
if (heldWeapon.getItem() instanceof ProjectileWeaponItem) {
Predicate<ItemStack> supportedProjectiles = ((ProjectileWeaponItem)heldWeapon.getItem()).getSupportedHeldProjectiles();
ItemStack heldProjectile = ProjectileWeaponItem.getHeldProjectile(this, supportedProjectiles);
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index 79f0bbfcf8ccdcbee99042d15adb5eb2338da124..0aec5c4b9c965a6f195aea4580c37c47123b0a50 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -2119,6 +2119,12 @@ public abstract class Player extends Avatar implements ContainerUser {

@Override
public ItemStack getProjectile(final ItemStack heldWeapon) {
+ // Purpur start - config for turning bundles into functional quivers
+ return getProjectile(heldWeapon, false, false);
+ }
+ @Override
+ public ItemStack getProjectile(ItemStack heldWeapon, boolean useBundleComponentStack, boolean useBundleItemStack) {
+ // Purpur end - config for turning bundles into functional quivers
if (!(heldWeapon.getItem() instanceof ProjectileWeaponItem)) {
return ItemStack.EMPTY;
}
@@ -2131,9 +2137,22 @@ public abstract class Player extends Avatar implements ContainerUser {
}

supportedProjectiles = ((ProjectileWeaponItem)heldWeapon.getItem()).getAllSupportedProjectiles().and(item -> this.tryReadyArrow(heldWeapon, item, anyEventCancelled)); // Paper - PlayerReadyArrowEvent
+ // Purpur start - config for turning bundles into functional quivers
+ ItemStack bundleProjectiles;
+ if (useBundleComponentStack) {
+ bundleProjectiles = getProjectileFromBundle(heldWeapon, supportedProjectiles);
+ if (!bundleProjectiles.isEmpty()) return bundleProjectiles;
+ }
+ // Purpur end - config for turning bundles into functional quivers

for (int i = 0; i < this.inventory.getContainerSize(); i++) {
ItemStack itemStack = this.inventory.getItem(i);
+ // Purpur start - config for turning bundles into functional quivers
+ if (useBundleItemStack) {
+ bundleProjectiles = itemStack.getItem() instanceof net.minecraft.world.item.BundleItem ? getProjectileFromBundle(itemStack, supportedProjectiles) : ItemStack.EMPTY;
+ if (!bundleProjectiles.isEmpty()) return bundleProjectiles;
+ }
+ // Purpur end - config for turning bundles into functional quivers
if (supportedProjectiles.test(itemStack)) {
return itemStack;
}
@@ -2143,6 +2162,39 @@ public abstract class Player extends Avatar implements ContainerUser {
return this.hasInfiniteMaterials() ? new ItemStack(Items.ARROW) : ItemStack.EMPTY;
}

+ // Purpur start - config for turning bundles into functional quivers
+ private ItemStack getProjectileFromBundle(ItemStack itemStack, Predicate<ItemStack> supportedProjectiles) {
+ if (!this.abilities.instabuild) {
+ net.minecraft.world.item.component.BundleContents bundleContents = itemStack.get(net.minecraft.core.component.DataComponents.BUNDLE_CONTENTS);
+ if (bundleContents == null || bundleContents.isEmpty()) {
+ return ItemStack.EMPTY;
+ }
+
+ Optional<ItemStack> first = bundleContents.itemCopyStream().filter(supportedProjectiles).findFirst();
+
+ if (first.isEmpty()) {
+ return ItemStack.EMPTY;
+ }
+
+ ItemStack firstItemStack = first.get();
+ net.minecraft.world.item.component.BundleContents.Mutable mutable = new net.minecraft.world.item.component.BundleContents.Mutable(bundleContents);
+ ItemStack removedItemStack = mutable.removeOne(firstItemStack);
+ if (removedItemStack == null) {
+ return ItemStack.EMPTY;
+ }
+
+ removedItemStack.shrink(1);
+ if (removedItemStack.getCount() != 0) {
+ mutable.tryInsert(removedItemStack);
+ }
+ itemStack.set(net.minecraft.core.component.DataComponents.BUNDLE_CONTENTS, mutable.toImmutable());
+ firstItemStack.setCount(1);
+ return firstItemStack;
+ }
+ return ItemStack.EMPTY;
+ }
+ // Purpur end - config for turning bundles into functional quivers
+
@Override
public Vec3 getRopeHoldPosition(final float partialTickTime) {
double xOff = 0.22 * (this.getMainArm() == HumanoidArm.RIGHT ? -1.0 : 1.0);
diff --git a/net/minecraft/world/item/BowItem.java b/net/minecraft/world/item/BowItem.java
index b8ec51d5f50c15f2cd74733f762b4ddc71b573cb..6df2b4e93d274ff2f06d18e22d1e02a5bcb62778 100644
--- a/net/minecraft/world/item/BowItem.java
+++ b/net/minecraft/world/item/BowItem.java
@@ -25,7 +25,7 @@ public class BowItem extends ProjectileWeaponItem {
@Override
public boolean releaseUsing(final ItemStack itemStack, final Level level, final LivingEntity entity, final int remainingTime) {
if (entity instanceof Player player) {
- ItemStack projectile = player.getProjectile(itemStack);
+ ItemStack projectile = player.getProjectile(itemStack, level.purpurConfig.bowUseBundleComponentAsQuiver, level.purpurConfig.bowUseBundleItemAsQuiver); // Purpur - config for turning bundles into functional quivers
// Purpur start - Infinity bow settings
if (level.purpurConfig.infinityWorksWithoutArrows && projectile.isEmpty() && net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.INFINITY, itemStack) > 0) {
projectile = new ItemStack(Items.ARROW);
diff --git a/net/minecraft/world/item/BundleItem.java b/net/minecraft/world/item/BundleItem.java
index f64ecce370edc04c363db8bce7eda473e2764d27..0094d21429195811e8ae98e3d4e41f31c9316fd3 100644
--- a/net/minecraft/world/item/BundleItem.java
+++ b/net/minecraft/world/item/BundleItem.java
@@ -143,7 +143,7 @@ public class BundleItem extends Item {
}

private void dropContent(final Level level, final Player player, final ItemStack itemStack) {
- if (this.dropContent(itemStack, player)) {
+ if (!(level.purpurConfig.bowUseBundleItemAsQuiver || level.purpurConfig.crossbowUseBundleItemAsQuiver) && this.dropContent(itemStack, player)) { // Purpur - config for turning bundles into functional quivers
playDropContentsSound(level, player);
player.awardStat(Stats.ITEM_USED.get(this));
}
diff --git a/net/minecraft/world/item/CrossbowItem.java b/net/minecraft/world/item/CrossbowItem.java
index d54f67ac95b1f93ea6d3db10160c68def11acc4e..1a376ce0a946cb27bb801da2e1c10be430fd2f75 100644
--- a/net/minecraft/world/item/CrossbowItem.java
+++ b/net/minecraft/world/item/CrossbowItem.java
@@ -68,7 +68,7 @@ public class CrossbowItem extends ProjectileWeaponItem {
if (chargedProjectiles != null && !chargedProjectiles.isEmpty()) {
this.performShooting(level, player, hand, itemStack, getShootingPower(chargedProjectiles), (float) level.purpurConfig.crossbowProjectileOffset, null); // Purpur - Projectile offset config
return InteractionResult.CONSUME;
- } else if (!player.getProjectile(itemStack).isEmpty()) {
+ } else if (!player.getProjectile(itemStack).isEmpty()) { // Purpur - config for turning bundles into functional quivers
this.startSoundPlayed = false;
this.midLoadSoundPlayed = false;
player.startUsingItem(hand);
@@ -95,7 +95,7 @@ public class CrossbowItem extends ProjectileWeaponItem {
}

private static boolean tryLoadProjectiles(final LivingEntity shooter, final ItemStack heldItem, final boolean consume) {
- List<ItemStack> drawn = draw(heldItem, shooter.getProjectile(heldItem), shooter, consume);
+ List<ItemStack> drawn = draw(heldItem, shooter.getProjectile(heldItem, shooter.level().purpurConfig.crossbowUseBundleComponentAsQuiver, shooter.level().purpurConfig.crossbowUseBundleItemAsQuiver), shooter, consume); // Purpur - config for turning bundles into functional quivers
// Paper end - Add EntityLoadCrossbowEvent
if (!drawn.isEmpty()) {
heldItem.set(DataComponents.CHARGED_PROJECTILES, ChargedProjectiles.ofNonEmpty(drawn));
diff --git a/net/minecraft/world/item/component/BundleContents.java b/net/minecraft/world/item/component/BundleContents.java
index 8d925a64f21c1599ea558256b0efd93e99d95fac..f85a32ac4f42422c4baefc7e6721526af0a10795 100644
--- a/net/minecraft/world/item/component/BundleContents.java
+++ b/net/minecraft/world/item/component/BundleContents.java
@@ -175,7 +175,12 @@ public final class BundleContents implements TooltipComponent {
}

private int findStackIndex(final ItemStack itemsToAdd) {
- if (!itemsToAdd.isStackable()) {
+ // Purpur start - config for turning bundles into functional quivers
+ return this.findStackIndex(itemsToAdd, false);
+ }
+ private int findStackIndex(final ItemStack itemsToAdd, boolean skipStackableCheck) {
+ if (!skipStackableCheck && !itemsToAdd.isStackable()) {
+ // Purpur end - config for turning bundles into functional quivers
return BundleContents.NO_STACK_INDEX;
}

@@ -253,12 +258,20 @@ public final class BundleContents implements TooltipComponent {
}

public @Nullable ItemStack removeOne() {
+ // Purpur start - config for turning bundles into functional quivers
+ return this.removeOne(null);
+ }
+ public @Nullable ItemStack removeOne(ItemStack itemStack2) {
+ // Purpur end - config for turning bundles into functional quivers
if (this.items.isEmpty()) {
return null;
}

int removeIndex = this.indexIsOutsideAllowedBounds(this.selectedItem) ? 0 : this.selectedItem;
- ItemStack stack = this.items.remove(removeIndex).copy();
+ // Purpur start - config for turning bundles into functional quivers
+ int stackIndex = itemStack2 != null ? this.findStackIndex(itemStack2, true) : -1;
+ ItemStack stack = this.items.remove(stackIndex == -1 ? removeIndex : stackIndex).copy();
+ // Purpur end - config for turning bundles into functional quivers
this.weight = this.weight.subtract(BundleContents.getWeight(stack).getOrThrow().multiplyBy(Fraction.getFraction(stack.getCount(), 1)));
this.toggleSelectedItem(BundleContents.NO_SELECTED_ITEM_INDEX);
return stack;
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,10 @@ private void infinityArrowsSettings() {
public boolean snowballExtinguishesFire = false;
public boolean snowballExtinguishesCandles = false;
public boolean snowballExtinguishesCampfires = false;
public boolean bowUseBundleItemAsQuiver = false;
public boolean bowUseBundleComponentAsQuiver = false;
public boolean crossbowUseBundleItemAsQuiver = false;
public boolean crossbowUseBundleComponentAsQuiver = false;
private void itemSettings() {
itemImmuneToCactus.clear();
getList("gameplay-mechanics.item.immune.cactus", new ArrayList<>()).forEach(key -> {
Expand Down Expand Up @@ -355,6 +359,10 @@ private void itemSettings() {
snowballExtinguishesFire = getBoolean("gameplay-mechanics.item.snowball.extinguish.fire", snowballExtinguishesFire);
snowballExtinguishesCandles = getBoolean("gameplay-mechanics.item.snowball.extinguish.candles", snowballExtinguishesCandles);
snowballExtinguishesCampfires = getBoolean("gameplay-mechanics.item.snowball.extinguish.campfires", snowballExtinguishesCampfires);
bowUseBundleItemAsQuiver = getBoolean("gameplay-mechanics.item.bow.use-bundle-as-quiver.item", bowUseBundleItemAsQuiver);
bowUseBundleComponentAsQuiver = getBoolean("gameplay-mechanics.item.bow.use-bundle-as-quiver.component", bowUseBundleComponentAsQuiver);
crossbowUseBundleItemAsQuiver = getBoolean("gameplay-mechanics.item.crossbow.use-bundle-as-quiver.item", crossbowUseBundleItemAsQuiver);
crossbowUseBundleComponentAsQuiver = getBoolean("gameplay-mechanics.item.crossbow.use-bundle-as-quiver.component", crossbowUseBundleComponentAsQuiver);
}

public double minecartMaxSpeed = 0.4D;
Expand Down
Loading