Booleans within CraftWorld#rayTrace

Discussion in 'Spigot Plugin Development' started by GreatThane, Jul 3, 2018.

  1. I've been working with this specific code snippet for a while now:
    Code (Java):
    Vec3D startPos = new Vec3D(getStart().getX(), getStart().getY(), getStart().getZ());
    Vec3D endPos = new Vec3D(getEnd().getX(), getEnd().getY(), getEnd().getZ());
    MovingObjectPosition hitResult = ((CraftWorld) getStart().getWorld()).getHandle()
            .rayTrace(startPos, endPos, false, true, false);
    return hitResult;
    And curiousity has gotten the better of me, as at the end of the method you will notice three booleans. I cannot for the life of me figure out what they do, other than the first (which when you follow it through its various NMS classes it will always turn to true, it has no impact). The second and third, however, I cannot figure out what they do, or why they are there. I get stuck at IBlockProperties, unable to figure out where they move from there.

    Does anyone here on the forum know what these booleans do? I have a sneaking suspicion that one controls whether to count entities and maybe the other for counting fluids or non-full blocks?
    I'm attempting to make a "wrapper object" of sorts, to make this calculation more friendly. If these booleans would give my object more control, I would love to know so I can add them.
  2. Why don't you step through in your ide to have a look-see?

    I would for you, but I'm at work :s
  3. That was my first idea, and how I figured out that the first boolean is pointless. However, the second and third lead to interfaces, which I don't think I'm quite smart enough to figure out what they do just based off the return and parameters, nor how to to find a class that extends them. I'm just not very experienced with NMS >.<
    I appreciate the thought though! Double checking is better than not checking in the first place. ^-^
  4. The interface is implemented by net.minecraft.server.WorldServer ;)
  5. Yeah, I... definitely am lost. WorldServer implements IAsynctaskHandler, and World (which it extends) implements IBlockAccess, and neither of these interfaces extend the interface I'm getting jammed at.
    Allow me to explain my exploration.
    I am able to get to World, which has the method rayTrace (easy enough, just a control click away). from there, I followed the first boolean (named "flag"), which I find only has two uses, both for Block.a(). from there, that just seems to return Block.m(), which just returns true no matter what.

    So, no matter what boolean "flag" is equal to, it has no effect on the method as it'll return true regardless. This is how I came to my conclusion of the first boolean having no effect.

    However, I ran into trouble with the second and third boolean. The second boolean, named "flag1," also has two uses, both with a "not" attached to them curiously enough. The first if statement flag1 is used in is used either if flag1 is set to false, or if both iblockdata (which as far as I can tell stores material, data, and other various information within a block? the variable appears to be set to the first provided block position through the Vec3D variable, passed in as the first parameter)'s method d(). IblockProperties.d() returns an AxisAlignedBB, which from what I can tell based off the object is a bounding box? I can't fully tell what happens here, as it is an interface. This bounding box is compared to the static final AxisAllignedBB variable in Block called k, which I'm unsure what it is set to. All I know is that if these two variables are not equal to each other, it passes true but only if a third boolean is also true (which this second boolean is true, as it relies on my explanation from "flag").

    Therefore, the if statement can be simplified to if flag1 is set to false, or if the starting block's bounding box is not equal to the predetermined bounding box of Block.k. Because flag1 is always used as "not flag1," I am assuming flag1 is an override of sorts, where when it is set to true it will ignore blocks with a specific bounding box.

    Finally, there is flag2, is only used in a set situation, where if it is set to true it should return the moving object position variable, and if it is set to false it should return null. Considering that a null return means that there has been no intersection, I am assuming flag2 is also a flag to ignore specific situations when set to false, but based on the code all I can tell is that when flag2 is set to true, it will allow for the start and end to return a hit detection if both points are on an intersecting point.

    Because of these factors, I can't seem to tell what these two variables mean. the second boolean is meant as some sort of override for a specific bounding box check, and the third boolean seems to allow for a single point detection?... I don't feel very confident in these conclusions.
    Therefore, the interface I'm getting jammed up with is IBlockProperties, specifically the method d().

    I apologize if I don't fully understand your response, unfortunately, I don't think I'm going to be able to understand without a little more of an explanation.
    I apologize if this inconveniences you.
  6. I'll be able to help next time I'm off work (in 2 days).

    In the mean time I would recommend setting up a Forge clone in your IDE, and a Spigot/Paper clone. These two projects (forge/spigot) side by side give me all the information I could ever want.

    Spigot is very hard to read because the old Bukkit team ditched MCP mappings back in 1.5 or something. They started deobfuscating things on their own (only bits and pieces though), which imho is a shit job. It's now refered to as NMS because it's mostly obfuscated crap still.

    Forge, on the other hand, has stuck true to MCP mappings. MCP has deobfuscated damn near everything. It's hard to find something without a meaningful name in it. Also, they include all the classes into the project so it's easier to step through the code (you won't get stick in an interface because you can step through the interface to any classes that implement them).

    The two project are still close enough to cross reference things. Once you've found what you want in NMS just go find it in Forge and then you can read and understand it better.

    Takes a little getting used to, but after awhile you'll get quicker at it. ;)
  7. Okay, I'll do my best! Thank you for the advice, I'll see if I can find the solution on my own. If I do, I'll edit this post with the explanation.
    Thank you for being patient with me, and I hope work goes well for you!

    EDIT: Oh my god this is amazing, everything has labels and logical names! according to forge:
    • The first boolean controls whether to stop on liquid
    • The second boolean controls whether to ignore blocks without bounding boxes
    • The third boolean controls whether or not to return on the last uncollidable block
    This means that that unknown bounding box I was running into before was for liquid blocks.

    Thank you so much for giving me the heads up for this resource, I have never dabbled with forge modding before, this makes most NMS files far easier to understand. I'm sure this will help me for a long time into the future.
    #7 GreatThane, Jul 3, 2018
    Last edited: Jul 3, 2018