|
| 1 | +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| 2 | + |
| 3 | +Date: Fri, 23 Feb 2024 01:48:08 +0000 |
| 4 | +Subject: [PATCH] Legacy player combat mechanics |
| 5 | + |
| 6 | + |
| 7 | +diff --git a/src/main/java/me/samsuik/sakura/utils/CombatUtil.java b/src/main/java/me/samsuik/sakura/utils/CombatUtil.java |
| 8 | +new file mode 100644 |
| 9 | +index 0000000000000000000000000000000000000000..6cda6ba8e29587fd04b727ef188484760c4ccdbd |
| 10 | +--- /dev/null |
| 11 | ++++ b/src/main/java/me/samsuik/sakura/utils/CombatUtil.java |
| 12 | +@@ -0,0 +1,37 @@ |
| 13 | ++package me.samsuik.sakura.utils; |
| 14 | ++ |
| 15 | ++import it.unimi.dsi.fastutil.objects.*; |
| 16 | ++import net.minecraft.core.registries.BuiltInRegistries; |
| 17 | ++import net.minecraft.world.item.*; |
| 18 | ++ |
| 19 | ++public final class CombatUtil { |
| 20 | ++ private static final Reference2FloatMap<Item> LEGACY_ITEM_DAMAGE_MAP = new Reference2FloatOpenHashMap<>(); |
| 21 | ++ |
| 22 | ++ public static float getLegacyItemDamage(Item item) { |
| 23 | ++ return LEGACY_ITEM_DAMAGE_MAP.getFloat(item); |
| 24 | ++ } |
| 25 | ++ |
| 26 | ++ private static float baseToolDamage(TieredItem item) { |
| 27 | ++ if (item instanceof SwordItem) return 4.0f; |
| 28 | ++ else if (item instanceof AxeItem) return 3.0f; |
| 29 | ++ else if (item instanceof PickaxeItem) return 2.0f; |
| 30 | ++ else if (item instanceof ShovelItem) return 1.0f; |
| 31 | ++ else return 0.0f; |
| 32 | ++ } |
| 33 | ++ |
| 34 | ++ static { |
| 35 | ++ LEGACY_ITEM_DAMAGE_MAP.defaultReturnValue(Float.MIN_VALUE); |
| 36 | ++ |
| 37 | ++ for (Item item : BuiltInRegistries.ITEM) { |
| 38 | ++ if (item instanceof TieredItem tieredItem) { |
| 39 | ++ LEGACY_ITEM_DAMAGE_MAP.put(item, baseToolDamage(tieredItem) + tieredItem.getTier().getAttackDamageBonus()); |
| 40 | ++ } |
| 41 | ++ |
| 42 | ++ if (item instanceof HoeItem) { |
| 43 | ++ LEGACY_ITEM_DAMAGE_MAP.put(item, 0.0f); |
| 44 | ++ } |
| 45 | ++ } |
| 46 | ++ |
| 47 | ++ //LEGACY_ITEM_DAMAGE_MAP.put(Items.TRIDENT, LEGACY_ITEM_DAMAGE_MAP.getFloat(Items.DIAMOND_SWORD)); |
| 48 | ++ } |
| 49 | ++} |
| 50 | +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java |
| 51 | +index 9fa79ba7f50fa20f3794fd955db1a4cc0fa8ee02..532fef2f50a0904a7c64bac30aa61dc71fcfc7dd 100644 |
| 52 | +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java |
| 53 | ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java |
| 54 | +@@ -276,6 +276,64 @@ public abstract class LivingEntity extends Entity implements Attackable { |
| 55 | + ++this.noActionTime; // Above all the floats |
| 56 | + } |
| 57 | + // Spigot end |
| 58 | ++ // Sakura start - legacy combat mechanics |
| 59 | ++ private static final UUID LEGACY_COMBAT_MECHANICS_UUID = UUID.fromString("84ef96f8-9f48-4ae4-a26c-e04551324816"); |
| 60 | ++ private static final AttributeModifier LEGACY_ATTACK_SPEED_MODIFIER = new AttributeModifier(LEGACY_COMBAT_MECHANICS_UUID, "Legacy attack speed", 100.0, AttributeModifier.Operation.ADDITION); |
| 61 | ++ |
| 62 | ++ private void updateAttackSpeedModifier() { |
| 63 | ++ AttributeInstance attackSpeed = this.getAttribute(Attributes.ATTACK_SPEED); |
| 64 | ++ if (attackSpeed != null) { |
| 65 | ++ attackSpeed.removeModifier(LEGACY_ATTACK_SPEED_MODIFIER); |
| 66 | ++ |
| 67 | ++ if (this.level().sakuraConfig().players.combat.legacyCombatMechanics) { |
| 68 | ++ attackSpeed.addTransientModifier(LEGACY_ATTACK_SPEED_MODIFIER); |
| 69 | ++ } |
| 70 | ++ } |
| 71 | ++ } |
| 72 | ++ |
| 73 | ++ protected final float getAttackDamageFromAttributes() { |
| 74 | ++ AttributeInstance attackDamage = this.getAttribute(Attributes.ATTACK_DAMAGE); |
| 75 | ++ AttributeModifier legacyModifier = null; |
| 76 | ++ |
| 77 | ++ if (this.level().sakuraConfig().players.combat.legacyCombatMechanics) { |
| 78 | ++ legacyModifier = this.getLegacyAttackModifier(); |
| 79 | ++ } |
| 80 | ++ |
| 81 | ++ final double damage; |
| 82 | ++ if (attackDamage == null || legacyModifier == null) { |
| 83 | ++ damage = this.getAttributeValue(Attributes.ATTACK_DAMAGE); |
| 84 | ++ } else { |
| 85 | ++ attackDamage.addTransientModifier(legacyModifier); |
| 86 | ++ damage = this.getAttributeValue(Attributes.ATTACK_DAMAGE); |
| 87 | ++ attackDamage.removeModifier(legacyModifier); |
| 88 | ++ } |
| 89 | ++ |
| 90 | ++ return (float) damage; |
| 91 | ++ } |
| 92 | ++ |
| 93 | ++ private @Nullable AttributeModifier getLegacyAttackModifier() { |
| 94 | ++ ItemStack itemstack = this.getLastHandItem(EquipmentSlot.MAINHAND); |
| 95 | ++ qt: if (!itemstack.hasTag() || !itemstack.getTag().contains("AttributeModifiers", 9)) { |
| 96 | ++ Collection<AttributeModifier> defaultModifiers = itemstack.getAttributeModifiers(EquipmentSlot.MAINHAND).get(Attributes.ATTACK_DAMAGE); |
| 97 | ++ double baseAttack = 0.0f; |
| 98 | ++ for (AttributeModifier mod : defaultModifiers) { |
| 99 | ++ if (mod.getOperation() != AttributeModifier.Operation.ADDITION) { |
| 100 | ++ break qt; |
| 101 | ++ } |
| 102 | ++ |
| 103 | ++ baseAttack += mod.getAmount(); |
| 104 | ++ } |
| 105 | ++ |
| 106 | ++ float legacyAttack = me.samsuik.sakura.utils.CombatUtil.getLegacyItemDamage(itemstack.getItem()); |
| 107 | ++ double attackDifference = (double) legacyAttack - baseAttack; |
| 108 | ++ |
| 109 | ++ if (baseAttack != 0.0f && legacyAttack != Float.MIN_VALUE) { |
| 110 | ++ return new AttributeModifier(LEGACY_COMBAT_MECHANICS_UUID, "Legacy attack damage", attackDifference, AttributeModifier.Operation.ADDITION); |
| 111 | ++ } |
| 112 | ++ } |
| 113 | ++ return null; |
| 114 | ++ } |
| 115 | ++ // Sakura end - legacy combat mechanics |
| 116 | + |
| 117 | + protected LivingEntity(EntityType<? extends LivingEntity> type, Level world) { |
| 118 | + super(type, world); |
| 119 | +@@ -2145,7 +2203,16 @@ public abstract class LivingEntity extends Entity implements Attackable { |
| 120 | + protected float getDamageAfterArmorAbsorb(DamageSource source, float amount) { |
| 121 | + if (!source.is(DamageTypeTags.BYPASSES_ARMOR)) { |
| 122 | + // this.hurtArmor(damagesource, f); // CraftBukkit - Moved into actuallyHurt(DamageSource, float) |
| 123 | ++ // Sakura start - legacy combat mechanics |
| 124 | ++ if (!this.level().sakuraConfig().players.combat.legacyCombatMechanics) { |
| 125 | + amount = CombatRules.getDamageAfterAbsorb(amount, (float) this.getArmorValue(), (float) this.getAttributeValue(Attributes.ARMOR_TOUGHNESS)); |
| 126 | ++ } else { |
| 127 | ++ // See: applyArmorModifier(DamageSource, float) |
| 128 | ++ int i = 25 - this.getArmorValue(); |
| 129 | ++ float f1 = amount * (float) i; |
| 130 | ++ amount = f1 / 25.0F; |
| 131 | ++ } |
| 132 | ++ // Sakura end - legacy combat mechanics |
| 133 | + } |
| 134 | + |
| 135 | + return amount; |
| 136 | +@@ -3201,6 +3268,12 @@ public abstract class LivingEntity extends Entity implements Attackable { |
| 137 | + if (!itemstack1.isEmpty()) { |
| 138 | + this.getAttributes().addTransientAttributeModifiers(itemstack1.getAttributeModifiers(enumitemslot)); |
| 139 | + } |
| 140 | ++ |
| 141 | ++ // Sakura start - legacy combat mechanics |
| 142 | ++ if (this instanceof ServerPlayer && enumitemslot == EquipmentSlot.MAINHAND) { |
| 143 | ++ this.updateAttackSpeedModifier(); |
| 144 | ++ } |
| 145 | ++ // Sakura end - legacy combat mechanics |
| 146 | + } |
| 147 | + } |
| 148 | + |
| 149 | +@@ -3354,7 +3427,7 @@ public abstract class LivingEntity extends Entity implements Attackable { |
| 150 | + this.lastArmorItemStacks.set(slot.getIndex(), armor); |
| 151 | + } |
| 152 | + |
| 153 | +- private ItemStack getLastHandItem(EquipmentSlot slot) { |
| 154 | ++ protected ItemStack getLastHandItem(EquipmentSlot slot) { // Sakura - legacy combat mechanics |
| 155 | + return (ItemStack) this.lastHandItemStacks.get(slot.getIndex()); |
| 156 | + } |
| 157 | + |
| 158 | +diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java |
| 159 | +index 8493566fec47ecef3fd7423b993d9e6e378df7e5..7f2b778706bdc1d24b97c53ac9278439a4a03d36 100644 |
| 160 | +--- a/src/main/java/net/minecraft/world/entity/player/Player.java |
| 161 | ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java |
| 162 | +@@ -1255,7 +1255,7 @@ public abstract class Player extends LivingEntity { |
| 163 | + if (playerAttackEntityEvent.callEvent() && willAttack) { // Logic moved to willAttack local variable. |
| 164 | + { |
| 165 | + // Paper end - PlayerAttackEntityEvent |
| 166 | +- float f = (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE); |
| 167 | ++ float f = this.getAttackDamageFromAttributes(); // Sakura - legacy combat mechanics |
| 168 | + float f1; |
| 169 | + |
| 170 | + if (target instanceof LivingEntity) { |
| 171 | +@@ -1266,8 +1266,14 @@ public abstract class Player extends LivingEntity { |
| 172 | + |
| 173 | + float f2 = this.getAttackStrengthScale(0.5F); |
| 174 | + |
| 175 | ++ // Sakura start - legacy combat mechanics |
| 176 | ++ if (!this.level().sakuraConfig().players.combat.legacyCombatMechanics) { |
| 177 | + f *= 0.2F + f2 * f2 * 0.8F; |
| 178 | + f1 *= f2; |
| 179 | ++ } else if (f1 != 0.0) { |
| 180 | ++ f1 += this.calculateLegacySharpnessDamage(); |
| 181 | ++ } |
| 182 | ++ // Sakura end - legacy combat mechanics |
| 183 | + // this.resetAttackCooldown(); // CraftBukkit - Moved to EntityLiving to reset the cooldown after the damage is dealt |
| 184 | + if (f > 0.0F || f1 > 0.0F) { |
| 185 | + boolean flag = f2 > 0.9F; |
| 186 | +@@ -1284,7 +1290,7 @@ public abstract class Player extends LivingEntity { |
| 187 | + boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity; // Paper - Add critical damage API; diff on change |
| 188 | + |
| 189 | + flag2 = flag2 && !this.level().paperConfig().entities.behavior.disablePlayerCrits; // Paper - Toggleable player crits |
| 190 | +- flag2 = flag2 && !this.isSprinting(); |
| 191 | ++ flag2 = flag2 && (this.level().sakuraConfig().players.combat.legacyCombatMechanics || !this.isSprinting()); // Sakura - legacy combat mechanics |
| 192 | + if (flag2) { |
| 193 | + f *= 1.5F; |
| 194 | + } |
| 195 | +@@ -1476,6 +1482,27 @@ public abstract class Player extends LivingEntity { |
| 196 | + } |
| 197 | + } |
| 198 | + |
| 199 | ++ // Sakura start - legacy combat mechanics |
| 200 | ++ private float calculateLegacySharpnessDamage() { |
| 201 | ++ ItemStack itemstack = this.getMainHandItem(); |
| 202 | ++ Map<net.minecraft.world.item.enchantment.Enchantment, Integer> enchantments = EnchantmentHelper.getEnchantments(itemstack); |
| 203 | ++ |
| 204 | ++ float legacy = 0.0f; |
| 205 | ++ float modern = 0.0f; |
| 206 | ++ |
| 207 | ++ for (Map.Entry<net.minecraft.world.item.enchantment.Enchantment, Integer> entry : enchantments.entrySet()) { |
| 208 | ++ if (entry.getKey() instanceof net.minecraft.world.item.enchantment.DamageEnchantment dmgEnchant && dmgEnchant.type == 0) { |
| 209 | ++ // sharpness: |
| 210 | ++ int level = entry.getValue(); |
| 211 | ++ legacy += (float) level * 1.25F; |
| 212 | ++ modern += dmgEnchant.getDamageBonus(level, MobType.UNDEFINED); |
| 213 | ++ } |
| 214 | ++ } |
| 215 | ++ |
| 216 | ++ return legacy - modern; |
| 217 | ++ } |
| 218 | ++ // Sakura end - legacy combat mechanics |
| 219 | ++ |
| 220 | + @Override |
| 221 | + protected void doAutoAttackOnTouch(LivingEntity target) { |
| 222 | + this.attack(target); |
0 commit comments