问题
I want to get the coordinates of the block the player is looking at. I tried to do it with:
double x = player.getLookVec().getX();
double y = player.getLookVec().getY();
double z = player.getLookVec().getZ();
But somehow these numbers are always between 0, 0, 0, and 1, 1, 1, so I didn't get the coordinates of the block. So how can I get the exact coordinates of a block?
More code:
@Mod.EventBusSubscriber (modid = FirstMod.MOD_ID, bus = Bus.FORGE)
public class RightClickBlock
{
@SubscribeEvent
public static void on(FOVUpdateEvent event)
{
if(player.getHeldItemMainhand().getItem() == Items.BEDROCK)
{
LivingEntity player = event.getEntity();
World worldIn = player.world;
double x = player.getLookVec().getX();
double y = player.getLookVec().getY();
double z = player.getLookVec().getZ(); `
worldIn.setBlockState(new BlockPos(x, y, z) , Blocks.BEDROCK.getDefaultState());
}
}
}
回答1:
Your attempt didn't work because getLookVec
tells you the direction the player is looking, not the position of what they're looking at. Anyway, you can only get what you want on the client, so if you want to use it on the server, you'll need to have the client send a packet to the server with it. With that said, here's how you get it:
RayTraceResult lookingAt = Minecraft.getMinecraft().objectMouseOver;
if (lookingAt != null && lookingAt.typeOfHit == RayTraceResult.Type.BLOCK) {
BlockPos pos = lookingAt.getBlockPos();
// now the coordinates you want are in pos. Example of use:
worldIn.setBlockState(pos, Blocks.BEDROCK.getDefaultState());
// this is a bit oversimplified - you have to send a packet to the server, since only the client knows the BlockPos, but only the server can change blocks
} else {
// not looking at a block, or too far away from one to tell
}
回答2:
Here's a class that I made for 1.13. You'll probably have to update it to 1.15. It's pretty similar to what Joseph Sible-Reinstate Monica was suggesting, but maybe it'll work better for your needs.
It takes a couple of parameters. You can leave partialTicks
null
, then set the range to how many blocks in a straight line you want to extend the path. Check out the RayTraceFluidMode
class to figure out what you need.
You can use the Minecraft
class to get that and the Entity
you want to trace from.
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.util.EntitySelectors;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.*;
import net.minecraft.world.chunk.IChunkProvider;
import javax.annotation.Nullable;
import java.util.List;
public class ExtendedRange
{
private Minecraft mc;
public RayTraceResult mcObjectMouseOver;
private final double range;
private final RayTraceFluidMode fluidMode;
private final Entity requestingEntity;
private Float partialTicks;
public boolean airTargeted;
public EnumFacing blockSideHit;
private IChunkProvider chunkProvider;
public ExtendedRange(@Nullable Float partialTicks, double range, RayTraceFluidMode fluidMode, Minecraft mc, Entity entity)
{
this.mc = mc;
if (partialTicks == null)
{
this.partialTicks = 1.0F;
}
this.range = range;
this.fluidMode = fluidMode;
this.requestingEntity = entity;
}
public void getMouseOver()
{
if (requestingEntity != null)
{
if (this.mc.world != null)
{
this.mc.profiler.startSection("pick");
Entity pointedEntity = null;
double d0 = range; // block reach distance. default 5.0D, max 1024.0D;
this.mcObjectMouseOver = requestingEntity.rayTrace(d0, partialTicks, fluidMode);
BlockPos blockPos = this.mcObjectMouseOver.getBlockPos();
IBlockState state = mc.world.getBlockState(blockPos);
this.blockSideHit = mcObjectMouseOver.sideHit;
this.airTargeted = state.isAir(mc.world, blockPos);
Vec3d vec3d = requestingEntity.getEyePosition(partialTicks);
boolean flag = false;
int i = 3;
double d1 = d0;
if (d0 > 3.0D) // if range is larger than 3 blocks
{
flag = true;
}
if (this.mcObjectMouseOver != null)
{
d1 = this.mcObjectMouseOver.hitVec.distanceTo(vec3d); // distance between ray trace and eye position
}
Vec3d vec3d1 = requestingEntity.getLook(1.0F); // get vector from angle of look
Vec3d vec3d2 = vec3d.add(vec3d1.x * d0, vec3d1.y * d0, vec3d1.z * d0); // add range multiplied by where entity is looking
Vec3d vec3d3 = null;
float f = 1.0F;
List<Entity> list = this.mc.world.getEntitiesInAABBexcluding(requestingEntity, requestingEntity.getBoundingBox().expand(vec3d1.x * d0, vec3d1.y * d0, vec3d1.z * d0).grow(1.0D, 1.0D, 1.0D), EntitySelectors.NOT_SPECTATING.and(Entity::canBeCollidedWith));
double d2 = d1; // d1 is either range or distance between ray trace and eye position
for (Entity entity1 : list)
{
AxisAlignedBB axisalignedbb = entity1.getBoundingBox().grow((double) entity1.getCollisionBorderSize());
RayTraceResult raytraceresult = axisalignedbb.calculateIntercept(vec3d, vec3d2); // vector between eye position and range location
if (axisalignedbb.contains(vec3d)) // if entity is intersected, set entity as intersected
{
if (d2 >= 0.0D)
{
pointedEntity = entity1;
this.airTargeted = false;
vec3d3 = raytraceresult == null ? vec3d : raytraceresult.hitVec;
d2 = 0.0D;
}
}
else if (raytraceresult != null) // run when entity is targeted...
{
double d3 = vec3d.distanceTo(raytraceresult.hitVec); // distance between eye position and range location
if (d3 < d2 || d2 == 0.0D)
{
if (entity1.getLowestRidingEntity() == requestingEntity.getLowestRidingEntity() && !entity1.canRiderInteract()) // if the entity found is what the requesting entity is riding
{
if (d2 == 0.0D)
{
pointedEntity = entity1;
this.airTargeted = false;
vec3d3 = raytraceresult.hitVec;
}
}
else
{
pointedEntity = entity1;
this.airTargeted = false;
vec3d3 = raytraceresult.hitVec;
d2 = d3;
}
}
}
}
if (pointedEntity != null && flag && vec3d.distanceTo(vec3d3) > 3.0D) // if * AND reach is greater than 3 blocks AND
{
this.mcObjectMouseOver = new RayTraceResult(RayTraceResult.Type.MISS, vec3d3, (EnumFacing) null, new BlockPos(vec3d3));
}
if (pointedEntity != null && (d2 < d1 || this.mcObjectMouseOver == null))
{
this.mcObjectMouseOver = new RayTraceResult(pointedEntity, vec3d3);
}
this.mc.profiler.endSection();
}
}
}
}
Then, to use the RayTraceResult
, you can do something like this:
Entity user = /* you can get the player from the Minecraft class and then convert it to an Entity */
ExtendedRange extendedRange = new ExtendedRange(null, range, RayTraceFluidMode.NEVER, Minecraft.getInstance(), user);
extendedRange.getMouseOver();
if (!extendedRange.airTargeted)
{
RayTraceResult result = extendedRange.mcObjectMouseOver;
Double blockX;
Double blockY;
Double blockZ;
if (result != null)
{
Entity hitEntity = result.entity;
if (hitEntity != null)
{
blockX = hitEntity.posX;
blockY = hitEntity.posY;
blockZ = hitEntity.posZ;
}
else
{
EnumFacing blockSideHit = extendedRange.blockSideHit;
Vec3d lookingAt = result.hitVec;
blockX = lookingAt.x;
blockY = lookingAt.y;
blockZ = lookingAt.z;
}
}
}
This will get you the coordinates or the first entity it hits.
Just a reminder: this is made for 1.13, so you'll have to make some changes to fix it.
来源:https://stackoverflow.com/questions/61717481/how-can-i-get-the-coordinates-of-a-block-the-player-is-looking-at