diff --git a/sakura-server/minecraft-patches/features/0013-Use-maxEntityCollision-limit-for-entity-retrieval.patch b/sakura-server/minecraft-patches/features/0013-Use-maxEntityCollision-limit-for-entity-retrieval.patch index ed45770..fe5d493 100644 --- a/sakura-server/minecraft-patches/features/0013-Use-maxEntityCollision-limit-for-entity-retrieval.patch +++ b/sakura-server/minecraft-patches/features/0013-Use-maxEntityCollision-limit-for-entity-retrieval.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Use maxEntityCollision limit for entity retrieval diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 7ed355448ff6fbcf585d82a88d456908f9eb3ae6..d0c013df89bb18ce0267b62461c69aaaec44e8c3 100644 +index d19a1528203bb6efa774ac60de8d6f8b3ad15473..3aee2a479a2e82aee1974b7360b716bbdbd3b0c5 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -3640,7 +3640,16 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3639,7 +3639,16 @@ public abstract class LivingEntity extends Entity implements Attackable { return; } // Paper end - don't run getEntities if we're not going to use its result diff --git a/sakura-server/minecraft-patches/sources/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java.patch b/sakura-server/minecraft-patches/sources/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java.patch new file mode 100644 index 0000000..1cb3a37 --- /dev/null +++ b/sakura-server/minecraft-patches/sources/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java +@@ -23,10 +_,10 @@ + this.items = NonNullList.withSize(items.size(), ItemStack.EMPTY); + + for (int i = 0; i < items.size(); i++) { +- this.items.set(i, items.get(i).copy()); ++ this.items.set(i, items.get(i).copyForPacket()); // Sakura - modify components sent to the client + } + +- this.carriedItem = carriedItem.copy(); ++ this.carriedItem = carriedItem.copyForPacket(); // Sakura - modify components sent to the client + } + + private ClientboundContainerSetContentPacket(RegistryFriendlyByteBuf buffer) { diff --git a/sakura-server/minecraft-patches/sources/net/minecraft/network/protocol/game/ClientboundContainerSetSlotPacket.java.patch b/sakura-server/minecraft-patches/sources/net/minecraft/network/protocol/game/ClientboundContainerSetSlotPacket.java.patch new file mode 100644 index 0000000..37f7734 --- /dev/null +++ b/sakura-server/minecraft-patches/sources/net/minecraft/network/protocol/game/ClientboundContainerSetSlotPacket.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/network/protocol/game/ClientboundContainerSetSlotPacket.java ++++ b/net/minecraft/network/protocol/game/ClientboundContainerSetSlotPacket.java +@@ -19,7 +_,7 @@ + this.containerId = containerId; + this.stateId = stateId; + this.slot = slot; +- this.itemStack = itemStack.copy(); ++ this.itemStack = itemStack.copyForPacket(); // Sakura - modify components sent to the client + } + + private ClientboundContainerSetSlotPacket(RegistryFriendlyByteBuf buffer) { diff --git a/sakura-server/minecraft-patches/sources/net/minecraft/world/entity/LivingEntity.java.patch b/sakura-server/minecraft-patches/sources/net/minecraft/world/entity/LivingEntity.java.patch index 6e55596..899db6b 100644 --- a/sakura-server/minecraft-patches/sources/net/minecraft/world/entity/LivingEntity.java.patch +++ b/sakura-server/minecraft-patches/sources/net/minecraft/world/entity/LivingEntity.java.patch @@ -126,20 +126,18 @@ } return damageAmount; -@@ -2248,7 +_,13 @@ +@@ -2248,6 +_,11 @@ com.google.common.base.Function blocking = new com.google.common.base.Function() { @Override public Double apply(Double f) { -+ // Sakura start - shield damage reduction -+ if (!level().sakuraConfig().players.combat.shieldDamageReduction || damagesource.getDirectEntity() instanceof AbstractArrow) { ++ // Sakura start - shield damage reduction & allow blocking with swords ++ if (LivingEntity.this.isBlockingWithSword() || LivingEntity.this.level().sakuraConfig().players.combat.shieldDamageReduction && !(damagesource.getDirectEntity() instanceof AbstractArrow)) { ++ return -(LivingEntity.this.isBlocking() ? f * 0.5 : 0.0); ++ } ++ // Sakura end - shield damage reduction & allow blocking with swords return -((LivingEntity.this.isDamageSourceBlocked(damagesource)) ? f : 0.0); -+ } else { -+ return -(LivingEntity.this.isBlocking() ? f * 0.5 : 0.0); -+ } -+ // Sakura end - shield damage reduction } }; - float blockingModifier = blocking.apply((double) amount).floatValue(); @@ -2344,6 +_,12 @@ // Apply damage to armor if (!damageSource.is(DamageTypeTags.BYPASSES_ARMOR)) { @@ -174,3 +172,22 @@ this.hurtServer(serverLevel, this.damageSources().drown(), 1.0F); } } +@@ -4047,8 +_,16 @@ + } + + public boolean isBlocking() { +- return this.getItemBlockingWith() != null; +- } ++ // Sakura start - allow blocking with swords ++ return this.getItemBlockingWith() != null || this.isBlockingWithSword(); ++ } ++ ++ public final boolean isBlockingWithSword() { ++ return this.isUsingItem() && !this.useItem.isEmpty() ++ && me.samsuik.sakura.configuration.GlobalConfiguration.get().players.combat.blockWithSwords ++ && this.useItem.getItem() instanceof me.samsuik.sakura.player.item.BlockableSwordItem; ++ } ++ // Sakura end - allow blocking with swords + + @Nullable + public ItemStack getItemBlockingWith() { diff --git a/sakura-server/minecraft-patches/sources/net/minecraft/world/item/Item.java.patch b/sakura-server/minecraft-patches/sources/net/minecraft/world/item/Item.java.patch new file mode 100644 index 0000000..1454934 --- /dev/null +++ b/sakura-server/minecraft-patches/sources/net/minecraft/world/item/Item.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/item/Item.java ++++ b/net/minecraft/world/item/Item.java +@@ -121,6 +_,11 @@ + return this.builtInRegistryHolder; + } + ++ // Sakura start - modify components sent to the client ++ public void modifyComponentsSentToClient(net.minecraft.core.component.PatchedDataComponentMap components) { ++ } ++ // Sakura end - modify components sent to the client ++ + public DataComponentMap components() { + return this.components; + } diff --git a/sakura-server/minecraft-patches/sources/net/minecraft/world/item/ItemStack.java.patch b/sakura-server/minecraft-patches/sources/net/minecraft/world/item/ItemStack.java.patch new file mode 100644 index 0000000..6e00132 --- /dev/null +++ b/sakura-server/minecraft-patches/sources/net/minecraft/world/item/ItemStack.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/item/ItemStack.java ++++ b/net/minecraft/world/item/ItemStack.java +@@ -826,6 +_,15 @@ + return this.getItem().interactLivingEntity(this, player, entity, usedHand); + } + ++ // Sakura start - modify components sent to the client ++ public ItemStack copyForPacket() { ++ ItemStack stackCopy = this.copy(); ++ Item item = stackCopy.getItem(); ++ item.modifyComponentsSentToClient(stackCopy.components); ++ return stackCopy; ++ } ++ // Sakura end - modify components sent to the client ++ + public ItemStack copy() { + // Paper start - Perf: Optimize Hoppers + return this.copy(false); diff --git a/sakura-server/minecraft-patches/sources/net/minecraft/world/item/Items.java.patch b/sakura-server/minecraft-patches/sources/net/minecraft/world/item/Items.java.patch index 5b5f630..e8bc645 100644 --- a/sakura-server/minecraft-patches/sources/net/minecraft/world/item/Items.java.patch +++ b/sakura-server/minecraft-patches/sources/net/minecraft/world/item/Items.java.patch @@ -1,5 +1,38 @@ --- a/net/minecraft/world/item/Items.java +++ b/net/minecraft/world/item/Items.java +@@ -1083,27 +_,27 @@ + public static final Item GOLD_INGOT = registerItem("gold_ingot"); + public static final Item NETHERITE_INGOT = registerItem("netherite_ingot", new Item.Properties().fireResistant()); + public static final Item NETHERITE_SCRAP = registerItem("netherite_scrap", new Item.Properties().fireResistant()); +- public static final Item WOODEN_SWORD = registerItem("wooden_sword", properties -> new SwordItem(ToolMaterial.WOOD, 3.0F, -2.4F, properties)); ++ public static final Item WOODEN_SWORD = registerItem("wooden_sword", properties -> new me.samsuik.sakura.player.item.BlockableSwordItem(ToolMaterial.WOOD, 3.0F, -2.4F, properties)); // Sakura - allow blocking with swords + public static final Item WOODEN_SHOVEL = registerItem("wooden_shovel", properties -> new ShovelItem(ToolMaterial.WOOD, 1.5F, -3.0F, properties)); + public static final Item WOODEN_PICKAXE = registerItem("wooden_pickaxe", properties -> new PickaxeItem(ToolMaterial.WOOD, 1.0F, -2.8F, properties)); + public static final Item WOODEN_AXE = registerItem("wooden_axe", properties -> new AxeItem(ToolMaterial.WOOD, 6.0F, -3.2F, properties)); + public static final Item WOODEN_HOE = registerItem("wooden_hoe", properties -> new HoeItem(ToolMaterial.WOOD, 0.0F, -3.0F, properties)); +- public static final Item STONE_SWORD = registerItem("stone_sword", properties -> new SwordItem(ToolMaterial.STONE, 3.0F, -2.4F, properties)); ++ public static final Item STONE_SWORD = registerItem("stone_sword", properties -> new me.samsuik.sakura.player.item.BlockableSwordItem(ToolMaterial.STONE, 3.0F, -2.4F, properties)); // Sakura - allow blocking with swords + public static final Item STONE_SHOVEL = registerItem("stone_shovel", properties -> new ShovelItem(ToolMaterial.STONE, 1.5F, -3.0F, properties)); + public static final Item STONE_PICKAXE = registerItem("stone_pickaxe", properties -> new PickaxeItem(ToolMaterial.STONE, 1.0F, -2.8F, properties)); + public static final Item STONE_AXE = registerItem("stone_axe", properties -> new AxeItem(ToolMaterial.STONE, 7.0F, -3.2F, properties)); + public static final Item STONE_HOE = registerItem("stone_hoe", properties -> new HoeItem(ToolMaterial.STONE, -1.0F, -2.0F, properties)); +- public static final Item GOLDEN_SWORD = registerItem("golden_sword", properties -> new SwordItem(ToolMaterial.GOLD, 3.0F, -2.4F, properties)); ++ public static final Item GOLDEN_SWORD = registerItem("golden_sword", properties -> new me.samsuik.sakura.player.item.BlockableSwordItem(ToolMaterial.GOLD, 3.0F, -2.4F, properties)); // Sakura - allow blocking with swords + public static final Item GOLDEN_SHOVEL = registerItem("golden_shovel", properties -> new ShovelItem(ToolMaterial.GOLD, 1.5F, -3.0F, properties)); + public static final Item GOLDEN_PICKAXE = registerItem("golden_pickaxe", properties -> new PickaxeItem(ToolMaterial.GOLD, 1.0F, -2.8F, properties)); + public static final Item GOLDEN_AXE = registerItem("golden_axe", properties -> new AxeItem(ToolMaterial.GOLD, 6.0F, -3.0F, properties)); + public static final Item GOLDEN_HOE = registerItem("golden_hoe", properties -> new HoeItem(ToolMaterial.GOLD, 0.0F, -3.0F, properties)); +- public static final Item IRON_SWORD = registerItem("iron_sword", properties -> new SwordItem(ToolMaterial.IRON, 3.0F, -2.4F, properties)); ++ public static final Item IRON_SWORD = registerItem("iron_sword", properties -> new me.samsuik.sakura.player.item.BlockableSwordItem(ToolMaterial.IRON, 3.0F, -2.4F, properties)); // Sakura - allow blocking with swords + public static final Item IRON_SHOVEL = registerItem("iron_shovel", properties -> new ShovelItem(ToolMaterial.IRON, 1.5F, -3.0F, properties)); + public static final Item IRON_PICKAXE = registerItem("iron_pickaxe", properties -> new PickaxeItem(ToolMaterial.IRON, 1.0F, -2.8F, properties)); + public static final Item IRON_AXE = registerItem("iron_axe", properties -> new AxeItem(ToolMaterial.IRON, 6.0F, -3.1F, properties)); + public static final Item IRON_HOE = registerItem("iron_hoe", properties -> new HoeItem(ToolMaterial.IRON, -2.0F, -1.0F, properties)); +- public static final Item DIAMOND_SWORD = registerItem("diamond_sword", properties -> new SwordItem(ToolMaterial.DIAMOND, 3.0F, -2.4F, properties)); ++ public static final Item DIAMOND_SWORD = registerItem("diamond_sword", properties -> new me.samsuik.sakura.player.item.BlockableSwordItem(ToolMaterial.DIAMOND, 3.0F, -2.4F, properties)); // Sakura - allow blocking with swords + public static final Item DIAMOND_SHOVEL = registerItem("diamond_shovel", properties -> new ShovelItem(ToolMaterial.DIAMOND, 1.5F, -3.0F, properties)); + public static final Item DIAMOND_PICKAXE = registerItem("diamond_pickaxe", properties -> new PickaxeItem(ToolMaterial.DIAMOND, 1.0F, -2.8F, properties)); + public static final Item DIAMOND_AXE = registerItem("diamond_axe", properties -> new AxeItem(ToolMaterial.DIAMOND, 5.0F, -3.0F, properties)); @@ -1194,6 +_,7 @@ public static final Item GOLDEN_APPLE = registerItem("golden_apple", new Item.Properties().food(Foods.GOLDEN_APPLE, Consumables.GOLDEN_APPLE)); public static final Item ENCHANTED_GOLDEN_APPLE = registerItem( diff --git a/sakura-server/src/main/java/me/samsuik/sakura/configuration/GlobalConfiguration.java b/sakura-server/src/main/java/me/samsuik/sakura/configuration/GlobalConfiguration.java index 3b9c66b..e4aaa37 100644 --- a/sakura-server/src/main/java/me/samsuik/sakura/configuration/GlobalConfiguration.java +++ b/sakura-server/src/main/java/me/samsuik/sakura/configuration/GlobalConfiguration.java @@ -41,6 +41,11 @@ public final class GlobalConfiguration extends ConfigurationPart { public Players players; public class Players extends ConfigurationPart { + public Combat combat = new Combat(); + public class Combat extends ConfigurationPart { + public boolean blockWithSwords = false; + } + public IntOr.Default bucketStackSize = IntOr.Default.USE_DEFAULT; public boolean stackableMilkBuckets = false; } diff --git a/sakura-server/src/main/java/me/samsuik/sakura/player/item/BlockableSwordItem.java b/sakura-server/src/main/java/me/samsuik/sakura/player/item/BlockableSwordItem.java new file mode 100644 index 0000000..ca0b5af --- /dev/null +++ b/sakura-server/src/main/java/me/samsuik/sakura/player/item/BlockableSwordItem.java @@ -0,0 +1,60 @@ +package me.samsuik.sakura.player.item; + +import me.samsuik.sakura.configuration.GlobalConfiguration; +import net.minecraft.core.component.DataComponents; +import net.minecraft.core.component.PatchedDataComponentMap; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.*; +import net.minecraft.world.item.component.Consumable; +import net.minecraft.world.level.Level; +import org.jspecify.annotations.NullMarked; + +@NullMarked +public final class BlockableSwordItem extends SwordItem { + private static final Consumable BLOCKING_ANIMATION = Consumable.builder() + .consumeSeconds(720000) + .animation(ItemUseAnimation.BLOCK) + .sound(BuiltInRegistries.SOUND_EVENT.wrapAsHolder(SoundEvents.EMPTY)) + .hasConsumeParticles(false) + .build(); + + public BlockableSwordItem(ToolMaterial material, float attackDamage, float attackSpeed, Properties properties) { + super(material, attackDamage, attackSpeed, properties); + } + + @Override + public void modifyComponentsSentToClient(PatchedDataComponentMap components) { + if (blockWithSwords()) { + components.set(DataComponents.CONSUMABLE, BLOCKING_ANIMATION); + } + } + + @Override + public InteractionResult use(Level level, Player player, InteractionHand hand) { + if (blockWithSwords()) { + ItemStack itemInHand = player.getItemInHand(hand); + return BLOCKING_ANIMATION.startConsuming(player, itemInHand, hand); + } + return super.use(level, player, hand); + } + + @Override + public ItemUseAnimation getUseAnimation(ItemStack stack) { + return blockWithSwords() ? ItemUseAnimation.BLOCK : super.getUseAnimation(stack); + } + + @Override + public int getUseDuration(ItemStack stack, LivingEntity entity) { + return blockWithSwords() ? 720000 : super.getUseDuration(stack, entity); + } + + private static boolean blockWithSwords() { + GlobalConfiguration config = GlobalConfiguration.get(); + return config != null && config.players.combat.blockWithSwords; + } +} diff --git a/sakura-server/src/main/java/me/samsuik/sakura/player/item/DataComponentHelper.java b/sakura-server/src/main/java/me/samsuik/sakura/player/item/DataComponentHelper.java index c6e830c..144cbeb 100644 --- a/sakura-server/src/main/java/me/samsuik/sakura/player/item/DataComponentHelper.java +++ b/sakura-server/src/main/java/me/samsuik/sakura/player/item/DataComponentHelper.java @@ -10,11 +10,6 @@ public final class DataComponentHelper { return config == null || !config.players.bucketStackSize.isDefined() ? -1 : config.players.bucketStackSize.intValue(); } - public static boolean stackableMilkBuckets() { - GlobalConfiguration config = GlobalConfiguration.get(); - return config != null && config.players.stackableMilkBuckets; - } - public static DataComponentMap copyComponentsAndModifyMaxStackSize(DataComponentMap componentMap, int maxItemSize) { if (maxItemSize > 0 && maxItemSize <= 99) { return DataComponentMap.builder() diff --git a/sakura-server/src/main/java/me/samsuik/sakura/player/item/MilkBucketItem.java b/sakura-server/src/main/java/me/samsuik/sakura/player/item/MilkBucketItem.java index 29e10af..81be9a1 100644 --- a/sakura-server/src/main/java/me/samsuik/sakura/player/item/MilkBucketItem.java +++ b/sakura-server/src/main/java/me/samsuik/sakura/player/item/MilkBucketItem.java @@ -15,8 +15,13 @@ public final class MilkBucketItem extends Item { @Override public void verifyComponentsAfterLoad(ItemStack stack) { int maxStackSize = DataComponentHelper.bucketMaxStackSize(); - if (DataComponentHelper.stackableMilkBuckets() && maxStackSize > 0 && maxStackSize < 100) { + if (maxStackSize > 0 && maxStackSize < 100 && stackableMilkBuckets()) { stack.set(DataComponents.MAX_STACK_SIZE, maxStackSize); } } + + private static boolean stackableMilkBuckets() { + GlobalConfiguration config = GlobalConfiguration.get(); + return config != null && config.players.stackableMilkBuckets; + } }