Jump to content
View in the app

A better way to browse. Learn more.

Forge Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Featured Replies

Posted

For the guns in my mod I am using ray tracing (kinda like hit scan) to check for a hit. For that purpose I have created a helper method that is fired on the server when a certain item is leftclicked. In a custom method in my ItemBase class that is confirmed to work I am calling this ray trace method:

ArrayList<HitData> hits = RayTraceUtils.rayTraceEntities(world, player, Utils.getPlayerPosition(player), player.getLookVec().normalize(), ConfigHandler.maxRange, 1);

The HitData object is just a wrapper around a RayTraceResult with additional data.

This is what this method then does:

public static ArrayList<HitData> rayTraceEntities(World world, EntityPlayer shooter, Position startPos, Vec3d dirVecNormal, int length, int maxHitCount)
{
    Vec3d startVec = new Vec3d(startPos.getX(), startPos.getY(), startPos.getZ());
    Vec3d endVec   = startVec.add(dirVecNormal.scale(length)).normalize();

    RayTraceResult result = world.rayTraceBlocks(startVec, endVec, false, true, false);

    Vec3d aabbVec1 = startVec.add(new Vec3d(0, -1, 0));
    Vec3d aabbVec2 = endVec.add(new Vec3d(0, 1, 0));

    AxisAlignedBB bb = new AxisAlignedBB(aabbVec1, result != null ? result.hitVec.add(new Vec3d(0, 1, 0)) : aabbVec2);
    List<Entity> entities = world.getEntitiesInAABBexcluding(shooter, bb, entityPredicate);

    ArrayList<HitData> entitiesInVector = new ArrayList<>();
    Vec3d startVecEntityCheck = startVec.normalize();
    Vec3d endVecEntityCheck = result != null ? result.hitVec.normalize() : endVec.normalize();

    for (Entity entity : entities)
    {
        EntityLivingBase victim = (EntityLivingBase)entity;
        if (!victim.noClip && victim.getCollisionBoundingBox() != null)
        {
            RayTraceResult intercept = victim.getCollisionBoundingBox().calculateIntercept(startVecEntityCheck, endVecEntityCheck);
            if (intercept != null)
            {
                intercept.hitInfo = isHeadshot(intercept.hitVec, intercept.entityHit);
                entitiesInVector.add(new HitData(victim, intercept, shooter));
                if (entitiesInVector.size() >= maxHitCount) { break; }
            }
        }
    }

    return entitiesInVector;
}

The Position object is kinda like BlockPos but with doubles instead of ints. For some reason this method always returns an empty list.

38 minutes ago, XFactHD said:

The Position object is kinda like BlockPos but with doubles instead of ints.

So a copy of Vec3d class?

 

startVec.add(dirVecNormal.scale(length)).normalize();

World::rayTraceBlocks takes a start vector and an end vector, not a start vector and a ray. By normalizing this vector you are essentially raycasting from startVec to around 0,0,0

38 minutes ago, XFactHD said:

entityPredicate

I assume this is a static predicate somewhere in this class? It would be nice to see this aswell.

 

38 minutes ago, XFactHD said:

Vec3d startVecEntityCheck = startVec.normalize();

Vec3d endVecEntityCheck = result != null ? result.hitVec.normalize() : endVec.normalize();

Again - normalizing a vector turns it into a [-1 - 1] vector. AxisAlignedBB's calculateIntercept method will pretty much always return null as long as the BB is not at 0,0,0(and it isn't as long as the entity itself is not at 0,0,0) because it compares the coordinates of the vector with it's coordinates.

You can see how vanilla raytraces entities at EntityRenderer::getMouseOver or for a cleaner code example at EntityArrow::findEntityOnPath

Edited by V0idWa1k3r

This is the entity predicate:

private static final Predicate<? super Entity> entityPredicate = Predicates.and(EntitySelectors.NOT_SPECTATING, new Predicate<Entity>()
{
    public boolean apply(@Nullable Entity entity) { return entity != null && entity.canBeCollidedWith() && entity instanceof EntityLivingBase; }
});

 

This is what I changed based on your comment on normalizing a vector (changes marked):

public static ArrayList<HitData> rayTraceEntities(World world, EntityPlayer shooter, Position startPos, Vec3d dirVecNormal, int length, int maxHitCount)
{
    Vec3d startVec = new Vec3d(startPos.getX(), startPos.getY(), startPos.getZ());
    Vec3d endVec   = startVec.add(dirVecNormal.scale(length)); <--

    RayTraceResult result = world.rayTraceBlocks(startVec, endVec, false, true, false);

    Vec3d aabbVec1 = startVec.add(new Vec3d(0, -1, 0));
    Vec3d aabbVec2 = endVec.add(new Vec3d(0, 1, 0));

    AxisAlignedBB bb = new AxisAlignedBB(aabbVec1, result != null ? result.hitVec.add(new Vec3d(0, 1, 0)) : aabbVec2);
    List<Entity> entities = world.getEntitiesInAABBexcluding(shooter, bb, entityPredicate);

    ArrayList<HitData> entitiesInVector = new ArrayList<>();
    Vec3d startVecEntityCheck = startVec; <--
    Vec3d endVecEntityCheck = result != null ? result.hitVec : endVec; <--

    for (Entity entity : entities)
    {
        EntityLivingBase victim = (EntityLivingBase)entity;
        if (!victim.noClip && victim.getCollisionBoundingBox() != null)
        {
            RayTraceResult intercept = victim.getCollisionBoundingBox().calculateIntercept(startVecEntityCheck, endVecEntityCheck);
            if (intercept != null)
            {
                intercept.hitInfo = isHeadshot(intercept.hitVec, intercept.entityHit);
                entitiesInVector.add(new HitData(victim, intercept, shooter));
                if (entitiesInVector.size() >= maxHitCount) { break; }
            }
        }
    }

    return entitiesInVector;
}

but this doesn't work either.

Entity::getCollisionBoundingBox appears to return null in most cases, so this check

9 minutes ago, XFactHD said:

if (!victim.noClip && victim.getCollisionBoundingBox() != null)

will always fail. Use Entity::getEntityBoundingBox instead.

That didn't help unfortunately.

That is strange. I used your code, corrected the following and it worked for the most part. Something must be wrong with something else then.

Could you please show the Utils::getPlayerPosition method? Make sure that you are adding the result of Entity::getEyeHeight to the Y coordinate

This is the getPlayerPosition method:

public static Position getPlayerPosition(EntityPlayer player)
{
    return new Position(player.posX, player.posY, player.posZ);
}

I changed this:

Vec3d startVec = new Vec3d(startPos.getX(), startPos.getY(), startPos.getZ());

to this:

Vec3d startVec = new Vec3d(startPos.getX(), startPos.getY() + shooter.getEyeHeight(), startPos.getZ());

as per your comment but it still doesn't work.

This is the full method right now:

public static ArrayList<HitData> rayTraceEntities(World world, EntityPlayer shooter, Position startPos, Vec3d dirVecNormal, int length, int maxHitCount)
{
    Vec3d startVec = new Vec3d(startPos.getX(), startPos.getY() + shooter.getEyeHeight(), startPos.getZ());
    Vec3d endVec   = startVec.add(dirVecNormal.scale(length));

    RayTraceResult result = world.rayTraceBlocks(startVec, endVec, false, true, false);

    Vec3d aabbVec1 = startVec.add(new Vec3d(0, -1, 0));
    Vec3d aabbVec2 = endVec.add(new Vec3d(0, 1, 0));

    AxisAlignedBB bb = new AxisAlignedBB(aabbVec1, result != null ? result.hitVec.add(new Vec3d(0, 1, 0)) : aabbVec2);
    List<Entity> entities = world.getEntitiesInAABBexcluding(shooter, bb, entityPredicate);

    ArrayList<HitData> entitiesInVector = new ArrayList<>();
    Vec3d endVecEntityCheck = result != null ? result.hitVec : endVec;

    for (Entity entity : entities)
    {
        EntityLivingBase victim = (EntityLivingBase)entity;
        if (!victim.noClip && victim.getEntityBoundingBox() != null)
        {
            RayTraceResult intercept = victim.getEntityBoundingBox().calculateIntercept(startVec, endVecEntityCheck);
            if (intercept != null)
            {
                intercept.hitInfo = isHeadshot(intercept.hitVec, intercept.entityHit);
                entitiesInVector.add(new HitData(victim, intercept, shooter));
                if (entitiesInVector.size() >= maxHitCount) { break; }
            }
        }
    }

    return entitiesInVector;
}

Well, I'm not really sure why is it not working for you. I can suggest removing the adition of the [0, 1, 0] vector here as it only offsets the actual calculations

15 minutes ago, XFactHD said:

result.hitVec.add(new Vec3d(0, 1, 0))

 

Could you please setup a github repository of your mod so I can debug it with a bit more than just this portion of the code you are giving? Because it works for me, that must mean that there is an issue somewhere else.

With the statement you quoted I am making sure that the AxisAlignedBoundingBox used for getEntittiesInAABB has a height of atleast one because an AABB with a height of zero can't intersect with anything.

I will create a GitHub repository and edit this post with the link.

EDIT: Here is the GitHub link: https://github.com/XFactHD/RainbowSixSiegeMC

Edited by XFactHD

Your RayTraceUtils::isHeadshot method is broken. If the entity passed is null it throws a NullPointerException that gets logged but due to the way the game processes the left click action it doesn't crash the game. And it is null because AxisAlignedBB::calculateIntercept has zero clues about any entities and thus is unable to pass one into the RayTraceResult's entityHit field value. You can safely pass the current entity being iterated into the method instead. 

 

As a side note: ItemMagazine::getSubItems is broken. As soon as you open the "search items" creative tab the game crashes because subItems contains all the items in the current tab, and for the search items tab it contains, well, all items added to tabs in the game. For some of them ItemStack::getMetadata will return a value greater than the size of your EnumMagazine enum.

Edited by V0idWa1k3r

I fixed it by setting the RayTraceResult's entityHit value to the entity currently being worked on as I need that value later on. Now it is working. Thank you very much for your great support.

 

Also, on your side note: this general error applys to many of the items in this mod.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

Important Information

By using this site, you agree to our Terms of Use.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.