From c2ad951336f701c06cc1d543c30e487ff0143b75 Mon Sep 17 00:00:00 2001 From: Brennan Ward Date: Sat, 21 May 2022 11:44:36 -0400 Subject: [PATCH] Add Attack Range attribute and Update Reach Distance (#8478) --- .../net/minecraft/client/Minecraft.java.patch | 19 +++- .../MultiPlayerGameMode.java.patch | 5 +- .../client/renderer/GameRenderer.java.patch | 34 +++++++ .../level/ServerPlayerGameMode.java.patch | 6 +- .../ServerGamePacketListenerImpl.java.patch | 25 ++++- .../world/entity/player/Player.java.patch | 14 ++- .../net/minecraft/world/item/Item.java.patch | 2 +- .../net/minecraftforge/common/ForgeMod.java | 11 ++- .../common/extensions/IForgePlayer.java | 95 +++++++++++++++++++ .../resources/assets/forge/lang/en_us.json | 2 + 10 files changed, 191 insertions(+), 22 deletions(-) create mode 100644 src/main/java/net/minecraftforge/common/extensions/IForgePlayer.java diff --git a/patches/minecraft/net/minecraft/client/Minecraft.java.patch b/patches/minecraft/net/minecraft/client/Minecraft.java.patch index e7a3d168fb..fcdf96ee4e 100644 --- a/patches/minecraft/net/minecraft/client/Minecraft.java.patch +++ b/patches/minecraft/net/minecraft/client/Minecraft.java.patch @@ -214,16 +214,21 @@ } } -@@ -1460,6 +_,8 @@ +@@ -1460,14 +_,20 @@ return false; } else { boolean flag = false; +- switch(this.f_91077_.m_6662_()) { + net.minecraftforge.client.event.InputEvent.ClickInputEvent inputEvent = net.minecraftforge.client.ForgeHooksClient.onClickInput(0, this.f_91066_.f_92096_, InteractionHand.MAIN_HAND); ++ HitResult.Type hitType = this.f_91077_.m_6662_(); ++ if(this.f_91077_ instanceof EntityHitResult entityHit) { // Forge: Perform attack range checks here, instead of in GameRenderer#pick, so extended-reach interactions work. ++ if(!f_91074_.canHit(entityHit.m_82443_(), 0)) hitType = HitResult.Type.MISS; // No padding in client code. ++ } + if (!inputEvent.isCanceled()) - switch(this.f_91077_.m_6662_()) { ++ switch(hitType) { case ENTITY: this.f_91072_.m_105223_(this.f_91074_, ((EntityHitResult)this.f_91077_).m_82443_()); -@@ -1467,7 +_,7 @@ + break; case BLOCK: BlockHitResult blockhitresult = (BlockHitResult)this.f_91077_; BlockPos blockpos = blockhitresult.m_82425_(); @@ -255,6 +260,14 @@ ItemStack itemstack = this.f_91074_.m_21120_(interactionhand); if (this.f_91077_ != null) { switch(this.f_91077_.m_6662_()) { +@@ -1506,6 +_,7 @@ + return; + } + ++ if(!this.f_91074_.canInteractWith(entityhitresult.m_82443_(), 0)) return; //Forge: Entity may be traced via attack range, but the player may not have sufficient reach. No padding in client code. + InteractionResult interactionresult = this.f_91072_.m_105230_(this.f_91074_, entity, entityhitresult, interactionhand); + if (!interactionresult.m_19077_()) { + interactionresult = this.f_91072_.m_105226_(this.f_91074_, entity, interactionhand); @@ -1513,6 +_,7 @@ if (interactionresult.m_19077_()) { diff --git a/patches/minecraft/net/minecraft/client/multiplayer/MultiPlayerGameMode.java.patch b/patches/minecraft/net/minecraft/client/multiplayer/MultiPlayerGameMode.java.patch index e3fad488df..e63e45d894 100644 --- a/patches/minecraft/net/minecraft/client/multiplayer/MultiPlayerGameMode.java.patch +++ b/patches/minecraft/net/minecraft/client/multiplayer/MultiPlayerGameMode.java.patch @@ -68,13 +68,12 @@ if (this.f_105193_ >= 1.0F) { this.f_105196_ = false; this.m_105272_(ServerboundPlayerActionPacket.Action.STOP_DESTROY_BLOCK, p_105284_, p_105285_); -@@ -227,7 +_,8 @@ +@@ -227,7 +_,7 @@ } public float m_105286_() { - return this.f_105197_.m_46408_() ? 5.0F : 4.5F; -+ float attrib = (float)f_105189_.f_91074_.m_21051_(net.minecraftforge.common.ForgeMod.REACH_DISTANCE.get()).m_22135_(); -+ return this.f_105197_.m_46408_() ? attrib : attrib - 0.5F; ++ return (float) this.f_105189_.f_91074_.getReachDistance(); } public void m_105287_() { diff --git a/patches/minecraft/net/minecraft/client/renderer/GameRenderer.java.patch b/patches/minecraft/net/minecraft/client/renderer/GameRenderer.java.patch index 6f385c1775..3f6a32b7b8 100644 --- a/patches/minecraft/net/minecraft/client/renderer/GameRenderer.java.patch +++ b/patches/minecraft/net/minecraft/client/renderer/GameRenderer.java.patch @@ -17,6 +17,40 @@ } catch (IOException ioexception) { list1.forEach((p_172772_) -> { p_172772_.getFirst().close(); +@@ -625,19 +_,21 @@ + boolean flag = false; + int i = 3; + double d1 = d0; ++ double atkRange = this.f_109059_.f_91074_.getAttackRange(); + if (this.f_109059_.f_91072_.m_105291_()) { +- d1 = 6.0D; ++ d1 = Math.max(d0, atkRange); + d0 = d1; + } else { +- if (d0 > 3.0D) { ++ if (d0 > atkRange) { + flag = true; + } + + d0 = d0; ++ d0 = d1 = Math.max(d0, atkRange); // Pick entities with the max of the reach distance and attack range. + } + + d1 *= d1; +- if (this.f_109059_.f_91077_ != null) { ++ if (this.f_109059_.f_91077_ != null && this.f_109059_.f_91077_.m_6662_() != HitResult.Type.MISS) { // Add != MISS to ensure Attack Range is not clamped at the value of Reach Distance. + d1 = this.f_109059_.f_91077_.m_82450_().m_82557_(vec3); + } + +@@ -652,7 +_,7 @@ + Entity entity1 = entityhitresult.m_82443_(); + Vec3 vec33 = entityhitresult.m_82450_(); + double d2 = vec3.m_82557_(vec33); +- if (flag && d2 > 9.0D) { ++ if (false && flag && d2 > 9.0D) { //Forge: Always keep the entity result to allow for extended reach interactions. + this.f_109059_.f_91077_ = BlockHitResult.m_82426_(vec33, Direction.m_122366_(vec31.f_82479_, vec31.f_82480_, vec31.f_82481_), new BlockPos(vec33)); + } else if (d2 < d1 || this.f_109059_.f_91077_ == null) { + this.f_109059_.f_91077_ = entityhitresult; @@ -706,7 +_,7 @@ d0 *= (double)Mth.m_14179_(this.f_109059_.f_91066_.f_92070_, 1.0F, 0.85714287F); } diff --git a/patches/minecraft/net/minecraft/server/level/ServerPlayerGameMode.java.patch b/patches/minecraft/net/minecraft/server/level/ServerPlayerGameMode.java.patch index 393df678b0..ca1e22f785 100644 --- a/patches/minecraft/net/minecraft/server/level/ServerPlayerGameMode.java.patch +++ b/patches/minecraft/net/minecraft/server/level/ServerPlayerGameMode.java.patch @@ -1,19 +1,17 @@ --- a/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -125,7 +_,15 @@ +@@ -125,7 +_,13 @@ double d1 = this.f_9245_.m_20186_() - ((double)p_9282_.m_123342_() + 0.5D) + 1.5D; double d2 = this.f_9245_.m_20189_() - ((double)p_9282_.m_123343_() + 0.5D); double d3 = d0 * d0 + d1 * d1 + d2 * d2; - if (d3 > 36.0D) { -+ double dist = f_9245_.m_21051_(net.minecraftforge.common.ForgeMod.REACH_DISTANCE.get()).m_22135_() + 1; + net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickBlock event = net.minecraftforge.common.ForgeHooks.onLeftClickBlock(f_9245_, p_9282_, p_9284_); + if (event.isCanceled() || (!this.m_9295_() && event.getUseItem() == net.minecraftforge.eventbus.api.Event.Result.DENY)) { // Restore block and te data + f_9245_.f_8906_.m_141995_(new ClientboundBlockBreakAckPacket(p_9282_, f_9244_.m_8055_(p_9282_), p_9283_, false, "mod canceled")); + f_9244_.m_7260_(p_9282_, f_9244_.m_8055_(p_9282_), f_9244_.m_8055_(p_9282_), 3); + return; + } -+ dist *= dist; -+ if (d3 > dist) { ++ if (!this.f_9245_.canInteractWith(p_9282_, 1)) { BlockState blockstate1; if (this.f_9245_.f_19853_.m_142572_() != null && this.f_9245_.m_146902_().m_45594_(new ChunkPos(p_9282_)) < this.f_9245_.f_19853_.m_142572_().m_6846_().m_11312_()) { blockstate1 = this.f_9244_.m_8055_(p_9282_); diff --git a/patches/minecraft/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch b/patches/minecraft/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch index 4e2fa053bf..a5b92b1e03 100644 --- a/patches/minecraft/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch +++ b/patches/minecraft/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch @@ -21,14 +21,12 @@ } public void m_7376_(ServerboundAcceptTeleportationPacket p_9835_) { -@@ -979,7 +_,9 @@ +@@ -979,7 +_,7 @@ this.f_9743_.m_9243_(); int i = this.f_9743_.f_19853_.m_151558_(); if (blockpos.m_123342_() < i) { - if (this.f_9766_ == null && this.f_9743_.m_20275_((double)blockpos.m_123341_() + 0.5D, (double)blockpos.m_123342_() + 0.5D, (double)blockpos.m_123343_() + 0.5D) < 64.0D && serverlevel.m_7966_(this.f_9743_, blockpos)) { -+ double dist = f_9743_.m_21051_(net.minecraftforge.common.ForgeMod.REACH_DISTANCE.get()).m_22135_() + 3; -+ dist *= dist; -+ if (this.f_9766_ == null && this.f_9743_.m_20275_((double)blockpos.m_123341_() + 0.5D, (double)blockpos.m_123342_() + 0.5D, (double)blockpos.m_123343_() + 0.5D) < dist && serverlevel.m_7966_(this.f_9743_, blockpos)) { ++ if (this.f_9766_ == null && this.f_9743_.canInteractWith(blockpos, 3) && serverlevel.m_7966_(this.f_9743_, blockpos)) { InteractionResult interactionresult = this.f_9743_.f_8941_.m_7179_(this.f_9743_, serverlevel, itemstack, interactionhand, blockhitresult); if (direction == Direction.UP && !interactionresult.m_19077_() && blockpos.m_123342_() >= i - 1 && m_9790_(this.f_9743_, itemstack)) { Component component = (new TranslatableComponent("build.tooHigh", i - 1)).m_130940_(ChatFormatting.RED); @@ -54,14 +52,31 @@ }, ChatType.CHAT, this.f_9743_.m_142081_()); } -@@ -1222,6 +_,7 @@ +@@ -1216,12 +_,13 @@ + return; + } + +- double d0 = 36.0D; +- if (this.f_9743_.m_20280_(entity) < 36.0D) { ++ if (true) { //Forge: Perform distance checks below since interactions and attacks differ. + p_9866_.m_179617_(new ServerboundInteractPacket.Handler() { private void m_143678_(InteractionHand p_143679_, ServerGamePacketListenerImpl.EntityInteraction p_143680_) { ++ if(!ServerGamePacketListenerImpl.this.f_9743_.canInteractWith(entity, 1.5D)) return; //Forge: If the entity cannot be reached, do nothing. Original check was dist < 6, range is 4.5, so vanilla used padding=1.5 ItemStack itemstack = ServerGamePacketListenerImpl.this.f_9743_.m_21120_(p_143679_).m_41777_(); InteractionResult interactionresult = p_143680_.m_143694_(ServerGamePacketListenerImpl.this.f_9743_, entity, p_143679_); + if (net.minecraftforge.common.ForgeHooks.onInteractEntityAt(f_9743_, entity, entity.m_20182_(), p_143679_) != null) return; if (interactionresult.m_19077_()) { CriteriaTriggers.f_10565_.m_61494_(ServerGamePacketListenerImpl.this.f_9743_, itemstack, entity); if (interactionresult.m_19080_()) { +@@ -1243,7 +_,7 @@ + + public void m_141994_() { + if (!(entity instanceof ItemEntity) && !(entity instanceof ExperienceOrb) && !(entity instanceof AbstractArrow) && entity != ServerGamePacketListenerImpl.this.f_9743_) { +- ServerGamePacketListenerImpl.this.f_9743_.m_5706_(entity); ++ if(ServerGamePacketListenerImpl.this.f_9743_.canHit(entity, 3)) ServerGamePacketListenerImpl.this.f_9743_.m_5706_(entity); //Forge: Perform attack range check. Original check was dist < 6, range is 3, so vanilla used padding=3 + } else { + ServerGamePacketListenerImpl.this.m_9942_(new TranslatableComponent("multiplayer.disconnect.invalid_entity_attacked")); + ServerGamePacketListenerImpl.f_9744_.warn("Player {} tried to attack an invalid entity", (Object)ServerGamePacketListenerImpl.this.f_9743_.m_7755_().getString()); @@ -1430,6 +_,8 @@ } diff --git a/patches/minecraft/net/minecraft/world/entity/player/Player.java.patch b/patches/minecraft/net/minecraft/world/entity/player/Player.java.patch index 4acc6ffd80..96a3f9905d 100644 --- a/patches/minecraft/net/minecraft/world/entity/player/Player.java.patch +++ b/patches/minecraft/net/minecraft/world/entity/player/Player.java.patch @@ -1,9 +1,11 @@ --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java -@@ -112,6 +_,7 @@ +@@ -111,7 +_,8 @@ + import net.minecraft.world.scores.Scoreboard; import net.minecraft.world.scores.Team; - public abstract class Player extends LivingEntity { +-public abstract class Player extends LivingEntity { ++public abstract class Player extends LivingEntity implements net.minecraftforge.common.extensions.IForgePlayer { + public static final String PERSISTED_NBT_TAG = "PlayerPersisted"; public static final String f_150081_ = "OfflinePlayer:"; public static final int f_150082_ = 16; @@ -23,7 +25,7 @@ public static AttributeSupplier.Builder m_36340_() { - return LivingEntity.m_21183_().m_22268_(Attributes.f_22281_, 1.0D).m_22268_(Attributes.f_22279_, (double)0.1F).m_22266_(Attributes.f_22283_).m_22266_(Attributes.f_22286_); -+ return LivingEntity.m_21183_().m_22268_(Attributes.f_22281_, 1.0D).m_22268_(Attributes.f_22279_, (double) 0.1F).m_22266_(Attributes.f_22283_).m_22266_(Attributes.f_22286_).m_22266_(net.minecraftforge.common.ForgeMod.REACH_DISTANCE.get()).m_22266_(Attributes.f_22282_); ++ return LivingEntity.m_21183_().m_22268_(Attributes.f_22281_, 1.0D).m_22268_(Attributes.f_22279_, (double) 0.1F).m_22266_(Attributes.f_22283_).m_22266_(Attributes.f_22286_).m_22266_(net.minecraftforge.common.ForgeMod.REACH_DISTANCE.get()).m_22266_(Attributes.f_22282_).m_22266_(net.minecraftforge.common.ForgeMod.ATTACK_RANGE.get()); } protected void m_8097_() { @@ -264,15 +266,17 @@ } float f4 = 0.0F; -@@ -1110,7 +_,7 @@ +@@ -1110,8 +_,8 @@ if (flag3) { float f3 = 1.0F + EnchantmentHelper.m_44821_(this) * f; - for(LivingEntity livingentity : this.f_19853_.m_45976_(LivingEntity.class, p_36347_.m_142469_().m_82377_(1.0D, 0.25D, 1.0D))) { +- if (livingentity != this && livingentity != p_36347_ && !this.m_7307_(livingentity) && (!(livingentity instanceof ArmorStand) || !((ArmorStand)livingentity).m_31677_()) && this.m_20280_(livingentity) < 9.0D) { + for(LivingEntity livingentity : this.f_19853_.m_45976_(LivingEntity.class, this.m_21120_(InteractionHand.MAIN_HAND).getSweepHitBox(this, p_36347_))) { - if (livingentity != this && livingentity != p_36347_ && !this.m_7307_(livingentity) && (!(livingentity instanceof ArmorStand) || !((ArmorStand)livingentity).m_31677_()) && this.m_20280_(livingentity) < 9.0D) { ++ if (livingentity != this && livingentity != p_36347_ && !this.m_7307_(livingentity) && (!(livingentity instanceof ArmorStand) || !((ArmorStand)livingentity).m_31677_()) && this.canHit(livingentity, 0)) { // Original check was dist < 3, range is 3, so vanilla used padding=0 livingentity.m_147240_((double)0.4F, (double)Mth.m_14031_(this.m_146908_() * ((float)Math.PI / 180F)), (double)(-Mth.m_14089_(this.m_146908_() * ((float)Math.PI / 180F)))); livingentity.m_6469_(DamageSource.m_19344_(this), f3); + } @@ -1152,13 +_,15 @@ EnchantmentHelper.m_44896_(this, p_36347_); ItemStack itemstack1 = this.m_21205_(); diff --git a/patches/minecraft/net/minecraft/world/item/Item.java.patch b/patches/minecraft/net/minecraft/world/item/Item.java.patch index a3df9e66fe..8ddaf5f075 100644 --- a/patches/minecraft/net/minecraft/world/item/Item.java.patch +++ b/patches/minecraft/net/minecraft/world/item/Item.java.patch @@ -109,7 +109,7 @@ float f7 = f2 * f4; - double d0 = 5.0D; - Vec3 vec31 = vec3.m_82520_((double)f6 * 5.0D, (double)f5 * 5.0D, (double)f7 * 5.0D); -+ double d0 = p_41437_.m_21051_(net.minecraftforge.common.ForgeMod.REACH_DISTANCE.get()).m_22135_();; ++ double d0 = p_41437_.getReachDistance(); + Vec3 vec31 = vec3.m_82520_((double)f6 * d0, (double)f5 * d0, (double)f7 * d0); return p_41436_.m_45547_(new ClipContext(vec3, vec31, ClipContext.Block.OUTLINE, p_41438_, p_41437_)); } diff --git a/src/main/java/net/minecraftforge/common/ForgeMod.java b/src/main/java/net/minecraftforge/common/ForgeMod.java index 22b25dd5e1..e9bae6d1b9 100644 --- a/src/main/java/net/minecraftforge/common/ForgeMod.java +++ b/src/main/java/net/minecraftforge/common/ForgeMod.java @@ -92,9 +92,18 @@ public class ForgeMod public static final RegistryObject NAMETAG_DISTANCE = ATTRIBUTES.register("nametag_distance", () -> new RangedAttribute("forge.nameTagDistance", 64.0D, 0.0D, 64.0).setSyncable(true)); public static final RegistryObject ENTITY_GRAVITY = ATTRIBUTES.register("entity_gravity", () -> new RangedAttribute("forge.entity_gravity", 0.08D, -8.0D, 8.0D).setSyncable(true)); - public static final RegistryObject REACH_DISTANCE = ATTRIBUTES.register("reach_distance", () -> new RangedAttribute("generic.reachDistance", 5.0D, 0.0D, 1024.0D).setSyncable(true)); + /** + * Reach Distance represents the distance at which a player may interact with the world. The default is 4.5 blocks. Players in creative mode have an additional 0.5 blocks of reach distance. + */ + public static final RegistryObject REACH_DISTANCE = ATTRIBUTES.register("reach_distance", () -> new RangedAttribute("generic.reachDistance", 4.5D, 0.0D, 1024.0D).setSyncable(true)); + + /** + * Attack Range represents the distance at which a player may attack an entity. The default is 3 blocks. Players in creative mode have an additional 3 blocks of attack reach. + */ + public static final RegistryObject ATTACK_RANGE = ATTRIBUTES.register("attack_range", () -> new RangedAttribute("generic.attack_range", 3.0D, 0.0D, 1024.0D).setSyncable(true)); public static final RegistryObject STEP_HEIGHT_ADDITION = ATTRIBUTES.register("step_height_addition", () -> new RangedAttribute("forge.stepHeight", 0.0D, -512.0D, 512.0D).setSyncable(true)); + private static boolean enableMilkFluid = false; public static final RegistryObject MILK = RegistryObject.create(new ResourceLocation("milk"), ForgeRegistries.FLUIDS); public static final RegistryObject FLOWING_MILK = RegistryObject.create(new ResourceLocation("flowing_milk"), ForgeRegistries.FLUIDS); diff --git a/src/main/java/net/minecraftforge/common/extensions/IForgePlayer.java b/src/main/java/net/minecraftforge/common/extensions/IForgePlayer.java new file mode 100644 index 0000000000..2bcdfc6bd1 --- /dev/null +++ b/src/main/java/net/minecraftforge/common/extensions/IForgePlayer.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.common.extensions; + +import java.util.Optional; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.ForgeMod; + +public interface IForgePlayer +{ + + private Player self() + { + return (Player) this; + } + + /** + * The attack range is increased by 3 for creative players, unless it is currently zero, which disables attacks. + * @return The attack range of this player. + */ + default double getAttackRange() + { + double range = self().getAttributeValue(ForgeMod.ATTACK_RANGE.get()); + return range == 0 ? 0 : range + (self().isCreative() ? 3 : 0); + } + + /** + * The reach distance is increased by 0.5 for creative players, unless it is currently zero, which disables interactions. + * @return The reach distance of this player. + */ + default double getReachDistance() + { + double reach = self().getAttributeValue(ForgeMod.REACH_DISTANCE.get()); + return reach == 0 ? 0 : reach + (self().isCreative() ? 0.5 : 0); + } + + /** + * Checks if the player can attack the passed entity.
+ * On the server, additional leniency is added to account for movement/lag. + * @param entity The entity being range-checked. + * @param padding Extra validation distance. + * @return If the player can attack the passed entity. + */ + default boolean canHit(Entity entity, double padding) // Do not rename to canAttack - will conflict with LivingEntity#canAttack + { + return isCloseEnough(entity, getAttackRange() + padding); + } + + /** + * Checks if the player can reach (right-click) the passed entity.
+ * On the server, additional leniency is added to account for movement/lag. + * @param entity The entity being range-checked. + * @param padding Extra validation distance. + * @return If the player can interact with the passed entity. + */ + default boolean canInteractWith(Entity entity, double padding) + { + return isCloseEnough(entity, getReachDistance() + padding); + } + + /** + * Utility check to see if the player is close enough to a target entity. + * @param entity The entity being checked against + * @param dist The max distance allowed + * @return If the eye-to-center distance between this player and the passed entity is less than dist. + */ + default boolean isCloseEnough(Entity entity, double dist) + { + Vec3 eye = self().getEyePosition(); + Vec3 targetCenter = entity.getPosition(1.0F).add(0, entity.getBbHeight() / 2, 0); + Optional hit = entity.getBoundingBox().clip(eye, targetCenter); //This hit should almost always be present, but we have a fallback just in case. It likely indicates lag if it is not present. + return (hit.isPresent() ? eye.distanceToSqr(hit.get()) : self().distanceToSqr(entity)) < dist * dist; + } + + /** + * Checks if the player can reach (right-click) a block.
+ * On the server, additional leniency is added to account for movement/lag. + * @param pos The position being range-checked. + * @param padding Extra validation distance. + * @return If the player can interact with this location. + */ + default boolean canInteractWith(BlockPos pos, double padding) + { + double reach = getReachDistance() + padding; + return self().getEyePosition().distanceToSqr(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D) < reach * reach; + } + +} diff --git a/src/main/resources/assets/forge/lang/en_us.json b/src/main/resources/assets/forge/lang/en_us.json index f78893c676..1c8300841b 100644 --- a/src/main/resources/assets/forge/lang/en_us.json +++ b/src/main/resources/assets/forge/lang/en_us.json @@ -186,10 +186,12 @@ "attribute.name.forge.nametag_distance": "Nametag Render Distance", "attribute.name.forge.entity_gravity": "Entity Gravity", "attribute.name.generic.reach_distance": "Reach Distance", + "attribute.name.generic.attack_range": "Attack Range", "forge.swimSpeed": "Swim Speed", "forge.nameTagDistance": "Nametag Render Distance", "forge.entity_gravity": "Entity Gravity", "generic.reachDistance": "Reach Distance", + "generic.attack_range": "Attack Range", "forge.stepHeight": "Step Height", "fluid.minecraft.milk": "Milk",