Skip to content

Commit

Permalink
Fix offhand
Browse files Browse the repository at this point in the history
  • Loading branch information
ZsoltMolnarrr committed Sep 9, 2024
1 parent 9229215 commit 8178b18
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 117 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# 2.0.2

- Fix enchantments on from offhand weapon strikes not being applied
- Fix offhand weapon strikes not reducing durability
- (NeoForge) Fix hand swapping two-handed items, causing offhand item deletion
- (NeoForge) Fix missing declaration to Cloth Config causing crash

Expand Down
35 changes: 21 additions & 14 deletions common/src/main/java/net/bettercombat/logic/PlayerAttackHelper.java
Original file line number Diff line number Diff line change
@@ -1,27 +1,16 @@
package net.bettercombat.logic;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
import net.bettercombat.BetterCombatMod;
import net.bettercombat.api.AttackHand;
import net.bettercombat.api.ComboState;
import net.bettercombat.api.WeaponAttributes;
import net.bettercombat.utils.AttributeModifierHelper;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.AttributeModifiersComponent;
import net.minecraft.entity.attribute.EntityAttribute;
import net.minecraft.entity.attribute.EntityAttributeModifier;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ShieldItem;
import net.minecraft.registry.entry.RegistryEntry;
import org.jetbrains.annotations.NotNull;

import java.util.Arrays;

import static net.minecraft.entity.EquipmentSlot.MAINHAND;

public class PlayerAttackHelper {
public static float getDualWieldingAttackDamageMultiplier(PlayerEntity player, AttackHand hand) {
return isDualWielding(player)
Expand Down Expand Up @@ -165,15 +154,33 @@ private static boolean evaluateCondition(WeaponAttributes.Condition condition, P

private static final Object attributesLock = new Object();

public static void offhandAttributes(PlayerEntity player, Runnable runnable) {
synchronized (attributesLock) {
public static void swapHandAttributes(PlayerEntity player, Runnable runnable) {
swapHandAttributes(player, true, runnable);
}

public static void swapHandAttributes(PlayerEntity player, boolean useOffHand, Runnable runnable) {
if (!useOffHand) {
runnable.run();
return;
}
synchronized (player) {
var inventory = player.getInventory();
var mainHandStack = player.getMainHandStack();
var offHandStack = inventory.offHand.get(0);

setAttributesForOffHandAttack(player, true);
inventory.main.set(inventory.selectedSlot, offHandStack);
inventory.offHand.set(0, offHandStack);

runnable.run();

inventory.main.set(inventory.selectedSlot, mainHandStack);
inventory.offHand.set(0, offHandStack);
setAttributesForOffHandAttack(player, false);
}
}

public static void setAttributesForOffHandAttack(PlayerEntity player, boolean useOffHand) {
private static void setAttributesForOffHandAttack(PlayerEntity player, boolean useOffHand) {
var mainHandStack = player.getMainHandStack();
var offHandStack = player.getOffHandStack();
ItemStack add;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ public void getAttributeValue_Inject(RegistryEntry<EntityAttribute> attribute, C
if (object instanceof PlayerEntity) {
var player = (PlayerEntity)object;
var comboCount = ((PlayerAttackProperties)player).getComboCount();
if (// player.getWorld().isClient &&
if (player.getWorld().isClient &&
comboCount > 0
&& PlayerAttackHelper.shouldAttackWithOffHand(player, comboCount)) {
PlayerAttackHelper.offhandAttributes(player, () -> {
PlayerAttackHelper.swapHandAttributes(player, () -> {
var value = player.getAttributes().getValue(attribute);
cir.setReturnValue(value);
});
Expand Down
190 changes: 90 additions & 100 deletions common/src/main/java/net/bettercombat/network/ServerNetwork.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,9 @@
import net.minecraft.util.Identifier;
import org.slf4j.Logger;

import java.util.UUID;

public class ServerNetwork {
static final Logger LOGGER = LogUtils.getLogger();

private static final UUID COMBO_DAMAGE_MODIFIER_ID = UUID.randomUUID();
private static final UUID DUAL_WIELDING_MODIFIER_ID = UUID.randomUUID();
private static final UUID SWEEPING_MODIFIER_ID = UUID.randomUUID();

public static void handleAttackAnimation(Packets.AttackAnimation packet, MinecraftServer server, ServerPlayerEntity player) {
ServerWorld world = Iterables.tryFind(server.getWorlds(), (element) -> element == player.getWorld())
.orNull();
Expand Down Expand Up @@ -92,124 +86,120 @@ public static void handleAttackRequest(Packets.C2S_AttackRequest request, Minecr
world.getServer().executeSync(() -> {
((PlayerAttackProperties)player).setComboCount(request.comboCount());

double damageBaseMultiplier = 0.0;
double range = 18.0;
if (attributes != null && attack != null) {
range = attributes.attackRange();
PlayerAttackHelper.swapHandAttributes(player, hand.isOffHand(), () -> {

double comboMultiplier = attack.damageMultiplier() - 1;
damageBaseMultiplier += comboMultiplier;
double damageBaseMultiplier = 0.0;
double range = 18.0;

var dualWieldingMultiplier = PlayerAttackHelper.getDualWieldingAttackDamageMultiplier(player, hand) - 1;
damageBaseMultiplier += dualWieldingMultiplier;

if (hand.isOffHand()) {
PlayerAttackHelper.setAttributesForOffHandAttack(player, true);
}
if (attributes != null && attack != null) {
range = attributes.attackRange();

SoundHelper.playSound(world, player, attack.swingSound());
double comboMultiplier = attack.damageMultiplier() - 1;
damageBaseMultiplier += comboMultiplier;

if (BetterCombatMod.config.allow_reworked_sweeping && request.entityIds().length > 1) {
double multiplier = 0
- (BetterCombatMod.config.reworked_sweeping_maximum_damage_penalty / BetterCombatMod.config.reworked_sweeping_extra_target_count)
* Math.min(BetterCombatMod.config.reworked_sweeping_extra_target_count, request.entityIds().length - 1);
var sweepRatio = player.getAttributeValue(EntityAttributes.PLAYER_SWEEPING_DAMAGE_RATIO);
var dualWieldingMultiplier = PlayerAttackHelper.getDualWieldingAttackDamageMultiplier(player, hand) - 1;
damageBaseMultiplier += dualWieldingMultiplier;

damageBaseMultiplier += multiplier + (BetterCombatMod.config.reworked_sweeping_maximum_damage_penalty * sweepRatio);
SoundHelper.playSound(world, player, attack.swingSound());

boolean playEffects = !BetterCombatMod.config.reworked_sweeping_sound_and_particles_only_for_swords
|| (hand.itemStack().getItem() instanceof SwordItem);
if (BetterCombatMod.config.reworked_sweeping_plays_sound && playEffects) {
world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.ENTITY_PLAYER_ATTACK_SWEEP, player.getSoundCategory(), 1.0f, 1.0f);
}
if (BetterCombatMod.config.reworked_sweeping_emits_particles && playEffects) {
player.spawnSweepAttackParticles();
if (BetterCombatMod.config.allow_reworked_sweeping && request.entityIds().length > 1) {
double multiplier = 0
- (BetterCombatMod.config.reworked_sweeping_maximum_damage_penalty / BetterCombatMod.config.reworked_sweeping_extra_target_count)
* Math.min(BetterCombatMod.config.reworked_sweeping_extra_target_count, request.entityIds().length - 1);
var sweepRatio = player.getAttributeValue(EntityAttributes.PLAYER_SWEEPING_DAMAGE_RATIO);

damageBaseMultiplier += multiplier + (BetterCombatMod.config.reworked_sweeping_maximum_damage_penalty * sweepRatio);

boolean playEffects = !BetterCombatMod.config.reworked_sweeping_sound_and_particles_only_for_swords
|| (hand.itemStack().getItem() instanceof SwordItem);
if (BetterCombatMod.config.reworked_sweeping_plays_sound && playEffects) {
world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.ENTITY_PLAYER_ATTACK_SWEEP, player.getSoundCategory(), 1.0f, 1.0f);
}
if (BetterCombatMod.config.reworked_sweeping_emits_particles && playEffects) {
player.spawnSweepAttackParticles();
}
}
}
}

Multimap<RegistryEntry<EntityAttribute>, EntityAttributeModifier> damageModifier = null;
if (damageBaseMultiplier != 0) {
AttributeModifierHelper.fromModifier(EntityAttributes.GENERIC_ATTACK_DAMAGE, null);
damageModifier = AttributeModifierHelper.fromModifier(
EntityAttributes.GENERIC_ATTACK_DAMAGE,
new EntityAttributeModifier(TEMPORARY_ATTACK, damageBaseMultiplier, EntityAttributeModifier.Operation.ADD_MULTIPLIED_BASE));
player.getAttributes().addTemporaryModifiers(damageModifier);
}
Multimap<RegistryEntry<EntityAttribute>, EntityAttributeModifier> damageModifier = null;
if (damageBaseMultiplier != 0) {
AttributeModifierHelper.fromModifier(EntityAttributes.GENERIC_ATTACK_DAMAGE, null);
damageModifier = AttributeModifierHelper.fromModifier(
EntityAttributes.GENERIC_ATTACK_DAMAGE,
new EntityAttributeModifier(TEMPORARY_ATTACK, damageBaseMultiplier, EntityAttributeModifier.Operation.ADD_MULTIPLIED_BASE));
player.getAttributes().addTemporaryModifiers(damageModifier);
}

var attackCooldown = PlayerAttackHelper.getAttackCooldownTicksCapped(player);
var knockbackMultiplier = BetterCombatMod.config.knockback_reduced_for_fast_attacks
? MathHelper.clamp(attackCooldown / 12.5F, 0.1F, 1F)
: 1F;
var lastAttackedTicks = ((LivingEntityAccessor)player).getLastAttackedTicks();
if (!useVanillaPacket) {
player.setSneaking(request.isSneaking());
}
var attackCooldown = PlayerAttackHelper.getAttackCooldownTicksCapped(player);
var knockbackMultiplier = BetterCombatMod.config.knockback_reduced_for_fast_attacks
? MathHelper.clamp(attackCooldown / 12.5F, 0.1F, 1F)
: 1F;
var lastAttackedTicks = ((LivingEntityAccessor) player).getLastAttackedTicks();
if (!useVanillaPacket) {
player.setSneaking(request.isSneaking());
}


var validationRangeSquared = range * range * BetterCombatMod.config.target_search_range_multiplier;
for (int entityId: request.entityIds()) {
// getEntityById(entityId);
boolean isBossPart = false;
Entity entity = world.getEntityById(entityId);
if (entity == null) {
isBossPart = true;
entity = world.getDragonPart(entityId); // Get LivingEntity or DragonPart
}
var validationRangeSquared = range * range * BetterCombatMod.config.target_search_range_multiplier;
for (int entityId : request.entityIds()) {
// getEntityById(entityId);
boolean isBossPart = false;
Entity entity = world.getEntityById(entityId);
if (entity == null) {
isBossPart = true;
entity = world.getDragonPart(entityId); // Get LivingEntity or DragonPart
}

if (entity == null
|| (entity.equals(player.getVehicle()) && !TargetHelper.isAttackableMount(entity))
|| (entity instanceof ArmorStandEntity && ((ArmorStandEntity)entity).isMarker())) {
continue;
}
if (entity instanceof LivingEntity livingEntity) {
if (BetterCombatMod.config.allow_fast_attacks) {
livingEntity.timeUntilRegen = 0;
if (entity == null
|| (entity.equals(player.getVehicle()) && !TargetHelper.isAttackableMount(entity))
|| (entity instanceof ArmorStandEntity && ((ArmorStandEntity) entity).isMarker())) {
continue;
}
if (knockbackMultiplier != 1F) {
((ConfigurableKnockback)livingEntity).setKnockbackMultiplier_BetterCombat(knockbackMultiplier);
if (entity instanceof LivingEntity livingEntity) {
if (BetterCombatMod.config.allow_fast_attacks) {
livingEntity.timeUntilRegen = 0;
}
if (knockbackMultiplier != 1F) {
((ConfigurableKnockback) livingEntity).setKnockbackMultiplier_BetterCombat(knockbackMultiplier);
}
}
}
((LivingEntityAccessor) player).setLastAttackedTicks(lastAttackedTicks);
// System.out.println("Server - Attacking hand: " + (hand.isOffHand() ? "offhand" : "mainhand") + " CD: " + player.getAttackCooldownProgress(0));
if (!isBossPart && useVanillaPacket) {
// System.out.println("HIT - A entity: " + entity.getEntityName() + " id: " + entity.getId() + " class: " + entity.getClass());
PlayerInteractEntityC2SPacket vanillaAttackPacket = PlayerInteractEntityC2SPacket.attack(entity, request.isSneaking());
handler.onPlayerInteractEntity(vanillaAttackPacket);
} else {
// System.out.println("HIT - B entity: " + entity.getEntityName() + " id: " + entity.getId() + " class: " + entity.getClass());
if (!BetterCombatMod.config.server_target_range_validation
|| player.squaredDistanceTo(entity) <= validationRangeSquared) {
if (entity instanceof ItemEntity || entity instanceof ExperienceOrbEntity || entity instanceof PersistentProjectileEntity || entity == player) {
handler.disconnect(Text.translatable("multiplayer.disconnect.invalid_entity_attacked"));
LOGGER.warn("Player {} tried to attack an invalid entity", (Object)player.getName().getString());
return;
((LivingEntityAccessor) player).setLastAttackedTicks(lastAttackedTicks);
// System.out.println("Server - Attacking hand: " + (hand.isOffHand() ? "offhand" : "mainhand") + " CD: " + player.getAttackCooldownProgress(0));
if (!isBossPart && useVanillaPacket) {
// System.out.println("HIT - A entity: " + entity.getEntityName() + " id: " + entity.getId() + " class: " + entity.getClass());
PlayerInteractEntityC2SPacket vanillaAttackPacket = PlayerInteractEntityC2SPacket.attack(entity, request.isSneaking());
handler.onPlayerInteractEntity(vanillaAttackPacket);
} else {
// System.out.println("HIT - B entity: " + entity.getEntityName() + " id: " + entity.getId() + " class: " + entity.getClass());
if (!BetterCombatMod.config.server_target_range_validation
|| player.squaredDistanceTo(entity) <= validationRangeSquared) {
if (entity instanceof ItemEntity || entity instanceof ExperienceOrbEntity || entity instanceof PersistentProjectileEntity || entity == player) {
handler.disconnect(Text.translatable("multiplayer.disconnect.invalid_entity_attacked"));
LOGGER.warn("Player {} tried to attack an invalid entity", (Object) player.getName().getString());
return;
}
player.attack(entity);
}
player.attack(entity);
}
}
if (entity instanceof LivingEntity livingEntity) {
if (knockbackMultiplier != 1F) {
((ConfigurableKnockback)livingEntity).setKnockbackMultiplier_BetterCombat(1F);
if (entity instanceof LivingEntity livingEntity) {
if (knockbackMultiplier != 1F) {
((ConfigurableKnockback) livingEntity).setKnockbackMultiplier_BetterCombat(1F);
}
}
}
}

if (!useVanillaPacket) {
player.updateLastActionTime();
}

if (!useVanillaPacket) {
player.updateLastActionTime();
}


if (damageModifier != null) {
player.getAttributes().removeModifiers(damageModifier);
}

if (hand.isOffHand()) {
PlayerAttackHelper.setAttributesForOffHandAttack(player, false);
}
if (damageModifier != null) {
player.getAttributes().removeModifiers(damageModifier);
}

((PlayerAttackProperties)player).setComboCount(-1);
((PlayerAttackProperties) player).setComboCount(-1);
});
});
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"parent": "bettercombat:sword"
"parent": "bettercombat:claymore"
}

0 comments on commit 8178b18

Please sign in to comment.