Add Attack Range attribute and Update Reach Distance (#8478)

This commit is contained in:
Brennan Ward authored and GitHub committed 2022-05-21 16:44:36 +01:00
1 parent 7fb5dfa3e6
commit c2ad951336
10 files changed
+191 -22

No files matched your search

@@ -92,9 +92,18 @@ public class ForgeMod
public static final RegistryObject<Attribute> NAMETAG_DISTANCE = ATTRIBUTES.register("nametag_distance", () -> new RangedAttribute("forge.nameTagDistance", 64.0D, 0.0D, 64.0).setSyncable(true));
public static final RegistryObject<Attribute> ENTITY_GRAVITY = ATTRIBUTES.register("entity_gravity", () -> new RangedAttribute("forge.entity_gravity", 0.08D, -8.0D, 8.0D).setSyncable(true));
public static final RegistryObject<Attribute> 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<Attribute> 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<Attribute> ATTACK_RANGE = ATTRIBUTES.register("attack_range", () -> new RangedAttribute("generic.attack_range", 3.0D, 0.0D, 1024.0D).setSyncable(true));
public static final RegistryObject<Attribute> 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<Fluid> MILK = RegistryObject.create(new ResourceLocation("milk"), ForgeRegistries.FLUIDS);
public static final RegistryObject<Fluid> FLOWING_MILK = RegistryObject.create(new ResourceLocation("flowing_milk"), ForgeRegistries.FLUIDS);
@@ -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.<br>
* 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.<br>
* 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<Vec3> 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.<br>
* 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;
}
}