Skip to content

Commit

Permalink
Reach and Crit Attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
minheragon12345 committed Dec 30, 2023
1 parent 11c6352 commit 85889b8
Show file tree
Hide file tree
Showing 12 changed files with 290 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.github.manasmods.manascore.attribute;

import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.Vec3;

import java.util.Optional;

public class ManasCoreAttributeUtils {
public static double getAttackRange(Player player) {
double range = player.getAttributeValue(ManasCoreAttributes.ENTITY_REACH.get());
return range == 0 ? 0 : range + (player.isCreative() ? 3 : 0);
}

public static double getReachDistance(Player player) {
double reach = player.getAttributeValue(ManasCoreAttributes.BLOCK_REACH.get());
return reach == 0 ? 0 : reach + (player.isCreative() ? 0.5 : 0);
}

public static boolean cantHit(Player player, Entity entity, double padding) {
Vec3 eye = player.getEyePosition();
Vec3 targetCenter = entity.getPosition(1.0F).add(0, entity.getBbHeight() / 2, 0);
Optional<Vec3> hit = entity.getBoundingBox().clip(eye, targetCenter);

double dist = getAttackRange(player) + padding;
return !(hit.map(eye::distanceToSqr).orElseGet(() -> player.distanceToSqr(entity)) < dist * dist);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
import net.minecraft.world.entity.ai.attributes.RangedAttribute;

public class ManasCoreAttributes {
public static final RegistrySupplier<RangedAttribute> BLOCK_REACH = ManasCore.REGISTER.attribute("block_reach")
.withDefaultValue(4.5)
.withMinimumValue(0)
.withMaximumValue(1024)
.applyTo(() -> EntityType.PLAYER)
.syncable()
.end();
public static final RegistrySupplier<RangedAttribute> CRIT_CHANCE = ManasCore.REGISTER.attribute("crit_chance")
.withDefaultValue(0)
.withMinimumValue(0)
Expand All @@ -20,13 +27,20 @@ public class ManasCoreAttributes {
.applyToAll()
.syncable()
.end();
public static final RegistrySupplier<RangedAttribute> JUMP_POWER = ManasCore.REGISTER.attribute("jump_power")
.withDefaultValue(0.42)
public static final RegistrySupplier<RangedAttribute> ENTITY_REACH = ManasCore.REGISTER.attribute("entity_reach")
.withDefaultValue(3)
.withMinimumValue(0)
.withMaximumValue(1024)
.applyTo(() -> EntityType.PLAYER)
.syncable()
.end();
public static final RegistrySupplier<RangedAttribute> JUMP_STRENGTH = ManasCore.REGISTER.attribute("jump_strength")
.withDefaultValue(0.42)
.withMinimumValue(0)
.withMaximumValue(1024)
.applyToAll()
.syncable()
.end();
public static final RegistrySupplier<RangedAttribute> MINING_SPEED_MULTIPLIER = ManasCore.REGISTER.attribute("mining_speed_multiplier")
.withDefaultValue(1.0)
.withMinimumValue(0)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.github.manasmods.manascore.core;

import com.github.manasmods.manascore.attribute.ManasCoreAttributeUtils;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.Constant;
import org.spongepowered.asm.mixin.injection.ModifyConstant;

@Mixin(Item.class)
public class MixinItem {
@ModifyConstant(method = "getPlayerPOVHitResult(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/level/ClipContext$Fluid;)Lnet/minecraft/world/phys/BlockHitResult;",
require = 4, allow = 4, constant = @Constant(doubleValue = 5.0))
private static double getReachDistance(double reachDistance, Level level, Player player) {
return ManasCoreAttributeUtils.getReachDistance(player);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.github.manasmods.manascore.attribute.ManasCoreAttributes;
import net.minecraft.tags.TagKey;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.level.material.Fluid;
Expand All @@ -21,21 +20,21 @@ public abstract class MixinLivingEntity {
@Inject(method = "getJumpPower", at = @At("RETURN"), cancellable = true)
protected void getJumpPower(CallbackInfoReturnable<Float> cir) {
LivingEntity entity = (LivingEntity) (Object) this;
AttributeInstance instance = entity.getAttribute(ManasCoreAttributes.JUMP_POWER.get());
AttributeInstance instance = entity.getAttribute(ManasCoreAttributes.JUMP_STRENGTH.get());
if (instance == null) return;

double newJump = (cir.getReturnValue() - getJumpBoostPower()) / 0.42 * instance.getValue();
double newJump = (cir.getReturnValue() - getJumpBoostPower()) / 0.42F * instance.getValue();
cir.setReturnValue((float) (newJump + getJumpBoostPower()));
}

@ModifyArg(method = "causeFallDamage", at = @At(value = "INVOKE",
target = "Lnet/minecraft/world/entity/Entity;causeFallDamage(FFLnet/minecraft/world/damagesource/DamageSource;)Z"), index = 0)
public float causeFallDamage(float fallDistance, float multiplier, DamageSource source) {
target = "Lnet/minecraft/world/entity/LivingEntity;calculateFallDamage(FF)I"), index = 0)
public float causeFallDamage(float fallDistance, float multiplier) {
LivingEntity entity = (LivingEntity) (Object) this;
AttributeInstance instance = entity.getAttribute(ManasCoreAttributes.JUMP_POWER.get());
AttributeInstance instance = entity.getAttribute(ManasCoreAttributes.JUMP_STRENGTH.get());
if (instance == null) return fallDistance;

float additionalJumpBlock = (float) ((instance.getValue() - 0.42) / 0.2);
float additionalJumpBlock = (float) ((instance.getValue() - 0.42F) / 0.1F);
return fallDistance - additionalJumpBlock;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,49 @@
package com.github.manasmods.manascore.core;

import com.github.manasmods.manascore.attribute.ManasCoreAttributeUtils;
import com.github.manasmods.manascore.attribute.ManasCoreAttributes;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.block.state.BlockState;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.*;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(Player.class)
public abstract class MixinPlayer {
@Redirect(method = "attack", at = @At(value = "INVOKE",
target = "Lnet/minecraft/world/entity/player/Player;getAttributeValue(Lnet/minecraft/world/entity/ai/attributes/Attribute;)D", opcode = Opcodes.GETSTATIC))
private double getAttackDamageWithCritChance(Player player, Attribute attribute) {
AttributeInstance instance = player.getAttribute(ManasCoreAttributes.CRIT_CHANCE.get());
if (instance == null || player.getRandom().nextInt(100) > instance.getValue())
return player.getAttributeValue(attribute);

boolean vanillaCrit = player.getAttackStrengthScale(0.5F) > 0.9F && player.fallDistance > 0.0F
&& !player.onGround() && !player.onClimbable() && !player.isInWater() && !player.isSprinting()
&& !player.hasEffect(MobEffects.BLINDNESS) && !player.isPassenger();
if (vanillaCrit) return player.getAttributeValue(attribute);

return player.getAttributeValue(attribute) * getCritMultiplier(1.5F);
}

@ModifyConstant(method = "attack(Lnet/minecraft/world/entity/Entity;)V", constant = @Constant(floatValue = 1.5F))
private float getCritMultiplier(float multiplier) {
Player player = (Player) (Object) this;
AttributeInstance instance = player.getAttribute(ManasCoreAttributes.CRIT_MULTIPLIER.get());
if (instance == null) return multiplier;
return (float) instance.getValue();
}

@ModifyConstant(method = "attack(Lnet/minecraft/world/entity/Entity;)V", constant = @Constant(doubleValue = 9.0))
private double getAttackRangeSquared(double attackRange) {
double range = ManasCoreAttributeUtils.getAttackRange((Player) (Object) this);
return range * range;
}

@Inject(method = "getDestroySpeed", at = @At("RETURN"), cancellable = true)
protected void getDestroySpeed(BlockState state, CallbackInfoReturnable<Float> cir) {
LivingEntity entity = (LivingEntity) (Object) this;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.github.manasmods.manascore.core;

import com.github.manasmods.manascore.attribute.ManasCoreAttributeUtils;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

@Mixin(ServerGamePacketListenerImpl.class)
public class MixinServerGamePacketListenerImpl {
@Shadow public ServerPlayer player;
@Redirect(method = "handleUseItemOn", at = @At(value = "FIELD",
target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;MAX_INTERACTION_DISTANCE:D", opcode = Opcodes.GETSTATIC))
private double getBlockInteractDistance() {
double reach = ManasCoreAttributeUtils.getReachDistance(this.player) + 3;
return reach * reach;
}

@Redirect(method = "handleInteract", at = @At(value = "FIELD",
target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;MAX_INTERACTION_DISTANCE:D", opcode = Opcodes.GETSTATIC))
private double getEntityInteractDistance() {
double reach = ManasCoreAttributeUtils.getAttackRange(this.player) + 3;
return reach * reach;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.github.manasmods.manascore.core;

import com.github.manasmods.manascore.attribute.ManasCoreAttributeUtils;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.level.ServerPlayerGameMode;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

@Mixin(ServerPlayerGameMode.class)
public class MixinServerPlayerGameMode {
@Shadow @Final protected ServerPlayer player;
@Redirect(method = "handleBlockBreakAction", at = @At(value = "FIELD",
target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;MAX_INTERACTION_DISTANCE:D", opcode = Opcodes.GETSTATIC))
private double getReachDistance() {
double reach = ManasCoreAttributeUtils.getReachDistance(player) + 1;
return reach * reach;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.github.manasmods.manascore.core.client;

import com.github.manasmods.manascore.attribute.ManasCoreAttributeUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.Constant;
import org.spongepowered.asm.mixin.injection.ModifyConstant;

@Mixin(GameRenderer.class)
public class MixinGameRenderer {
@Shadow @Final Minecraft minecraft;
@ModifyConstant(method = "pick", require = 1, allow = 1, constant = @Constant(doubleValue = 6.0))
private double getReachDistance(double reachDistance) {
Player player = this.minecraft.player;
if (player == null) return reachDistance;
return ManasCoreAttributeUtils.getReachDistance(player);
}

@ModifyConstant(method = "pick", constant = @Constant(doubleValue = 9.0))
private double getAttackRange(double attackRange) {
Player player = this.minecraft.player;
if (player == null) return attackRange;
double range = ManasCoreAttributeUtils.getAttackRange(player);
return range * range;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.github.manasmods.manascore.core.client;

import com.github.manasmods.manascore.attribute.ManasCoreAttributeUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.Constant;
import org.spongepowered.asm.mixin.injection.ModifyConstant;

@Mixin(Gui.class)
public class MixinGui {
@Shadow @Final
private Minecraft minecraft;
@ModifyConstant(method = "renderCrosshair", require = 2, allow = 1, constant = @Constant(floatValue = 1.0F))
private float getActualReachDistance(float constant) {
Player player = minecraft.player;
if (player == null) return constant;
if (minecraft.crosshairPickEntity == null) return constant;

if (ManasCoreAttributeUtils.cantHit(player, minecraft.crosshairPickEntity, 0)) return 2.0F;
return constant;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.github.manasmods.manascore.core.client;

import com.github.manasmods.manascore.attribute.ManasCoreAttributeUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.multiplayer.MultiPlayerGameMode;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.HitResult;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(Minecraft.class)
public class MixinMinecraft {
@Shadow protected int missTime;
@Shadow @Nullable public HitResult hitResult;

@Shadow @Nullable public LocalPlayer player;
@Shadow @Nullable public MultiPlayerGameMode gameMode;

@Shadow @Nullable public ClientLevel level;
@Inject(method = "startAttack", at = @At("HEAD"), cancellable = true)
private void startAttack(CallbackInfoReturnable<Boolean> cir) {
if (this.missTime > 0) return;
if (this.hitResult == null) return;

LocalPlayer player = this.player;
if (player == null) return;
if (player.isHandsBusy()) return;

ItemStack itemStack = this.player.getItemInHand(InteractionHand.MAIN_HAND);
if (level != null && !itemStack.isItemEnabled(level.enabledFeatures())) {
cir.setReturnValue(false);
return;
}

if(!(this.hitResult instanceof EntityHitResult entityHit)) return;
if(ManasCoreAttributeUtils.cantHit(player, entityHit.getEntity(), 0)) {
if (this.gameMode != null && this.gameMode.hasMissTime()) this.missTime = 10;
this.player.resetAttackStrengthTicker();
this.player.swing(InteractionHand.MAIN_HAND);
cir.setReturnValue(false);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.github.manasmods.manascore.core.client;

import com.github.manasmods.manascore.attribute.ManasCoreAttributeUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.MultiPlayerGameMode;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(MultiPlayerGameMode.class)
public class MixinMultiPlayerGameMode {
@Shadow @Final private Minecraft minecraft;
@Inject(method = "getPickRange", at = @At("HEAD"), cancellable = true)
protected void getPickRange(CallbackInfoReturnable<Float> cir) {
Player player = this.minecraft.player;
if (player == null) return;
cir.setReturnValue((float) ManasCoreAttributeUtils.getReachDistance(player));
}
}
9 changes: 8 additions & 1 deletion common/src/main/resources/manascore-common.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,20 @@
"MixinChunkSerializer",
"MixinDataFixTypes",
"MixinEntity",
"MixinItem",
"MixinLevel",
"MixinLevelChunk",
"MixinLivingEntity",
"MixinPlayer",
"MixinServerLevel"
"MixinServerGamePacketListenerImpl",
"MixinServerLevel",
"MixinServerPlayerGameMode"
],
"client": [
"client.MixinGameRenderer",
"client.MixinGui",
"client.MixinMinecraft",
"client.MixinMultiPlayerGameMode"
],
"injectors": {
"defaultRequire": 1
Expand Down

0 comments on commit 85889b8

Please sign in to comment.