Jump to content

[1.8] Check if player is looking at the moon, whilst holding an item


DARKHAWX

Recommended Posts

Hey there,

So just like the title says, I want to have an item that when held will check, each tick, whether the player is holding said item, and if so, determine whether they are looking at the moon (the player must have line of sight, so no blocks in the way).

 

Now, I have a few small snippets of code that I'm pretty sure work, but I don't know how to piece it all together.

For example I think I can use

onUpdate()

to perform the checks each tick (and I think it also comes with a built in checkiftheplayerisholdingtheitem).

 

And I'm also sure that I can use

getCelestialAngle(0)

(with a bit of math I'm told) to get the current angle of the moon, and use

getLookVec()

to get the look vector of the player. But with all of this info I don't know how to put it together, and also how to check if the player can actually see the moon (there are no blocks in between). Does anyone know of a way to put this all together so it works?

 

 

No signature for you!

Link to comment
Share on other sites

With the lookvec there is a method to find the first non air block it finds to check for collisions.  I can't remember the name off the top of my head.  However, if you look out 100 blocks or so and see nothing but air, safe to say you can see the sky.  You need to play with the number until you are happy with it.

 

To see the moon though, you need to know exactly where it is in the sky.  the celestial angle will not be the whole story, there is another axis.  That is going to get somewhat complicated.  I think the moons/sun probably travels upon the x or z axis and the angle refers to the other axis.  There will be some trig in there for you to figure out what angle to the player that is and check to see if his look vector lines up with it.

 

Are you sure you want to do this?  Its going to get messy.

Long time Bukkit & Forge Programmer

Happy to try and help

Link to comment
Share on other sites

Yes, I do want to do this.

 

I knew it was probably going to be a bit messy, but I enjoy a challenge. The Maths part I'm not worried about at all. The main part I'm having trouble with us understand what methods I SHOULD be using together to find this out, and exactly what each methods returns.

 

 

 

As a super side note: how can I make a player hold my item like a thaumometer, or a map (when it covers the players screen)?

No signature for you!

Link to comment
Share on other sites

As far as i know the sun and moon are rendered based on the player position going from east to west meaning the x-Axis.

therefore i would try the following:

get the Look vector lets call him lv = player.getLook(1.0F); (length is 1)

now check if the z coordinate is close to 0 (by a chosen threshold you have to find out, maybe 0.1) meaning the player is looking east or west.

if that's true. set lv.z to 0 and create a vec3 x = new Vec3(1,0,0) basically the x-Axis.

With lv.dotproduct(x) you get the angle the player is looking up or down (in respect to the x-Axis). compare it the CelestialAngle (check with threshold, again) and TADA you are looking at the moon.

 

small hint: i don't know how the CelestialAngle is measured so this is only the basic idea i had after reading your question. it will be a lot of trial and error. For the line of sight, check OpenModularTurret on github. awesome coding-style, easy to read and helped me to write my own. https://github.com/OpenModularTurretsTeam/OpenModularTurrets/blob/master/src/main/java/openmodularturrets/util/TurretHeadUtil.java

It doesn't work, I don't know why.

It works, I don't know why.

Link to comment
Share on other sites

When you say "looking at", do you mean having the Moon in his cross-hairs? If so, then look for an aim method. I think the moon is an entity, so you might be able to get a bead on it like any other entity. You might hunt for where mobs try to see players to get clues.

 

Also: The graphics engine must do visibility math before deciding whether to render the moon graphically. If you can peek at its determination (client side only, and only if the player is using self point-of-view) then you can skip some maths. How and when you send a message to the server might be tricky though. Does the server even need to know? I missed the upshot of what you want to have happen when you test positive. If it's a purely visual effect, then the server doesn't need it.

 

BTW, All line-of-sight methods will have at least one hole: If a player is in a long enough East-West tunnel right at moon-rise or set, then the tunnel can pierce the rendering distance, making the moon visible even deep underground.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Link to comment
Share on other sites

-snip-

 

BTW, All line-of-sight methods will have at least one hole: If a player is in a long enough East-West tunnel right at moon-rise or set, then the tunnel can pierce the rendering distance, making the moon visible even deep underground.

That would be a problem... I'll have to look into some way of blocking this...

No signature for you!

Link to comment
Share on other sites

That would be a problem... I'll have to look into some way of blocking this...

 

if(player.posY < 64) { //probably underground }

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

That would be a problem... I'll have to look into some way of blocking this...

 

if(player.posY < 64) { //probably underground }

Well that's an easy solution, but it probably isn't the best.

 

 

So this is what I've got so far. It works and is accurate enough, but currently doesn't check if the player has a clear line of sight.

    /**
     * Checks if the player is looking at a celestial body to a certain degree of accuracy
     * @param player = player to check agains
     * @param threshold = maximum difference between the angles (degree of accuracy)
     * @param checkMoon = whether to instead check if the player is looking at the moon
     * @param throughWalls = whether to check if the player has a clear line of sight (not implemented yet)
     * @return true if difference between angles is less than threshold, false otherwise
     */
    public static boolean isLookingAtSun(EntityPlayer player, int threshold, boolean checkMoon, boolean throughWalls) {
        World worldIn = player.getEntityWorld();
        // Maximum range to check if they have clear line of sight
        int maxRange = 128;
        // Some math (returns a value between 0 and 1 depending on if its at the horizon or vertical
        double moonHeightVal = Math.sin((worldIn.getCelestialAngle(0) + 0.25f) * 2 * Math.PI);
        double time = worldIn.getWorldTime();
        double correctAngle = -1;
        // The players look vector
        Vec3 vector = player.getLookVec();
        double angle;

        // Angle will now be between 0 and 4. 0 = 0 degrees, 1 = 90 degrees, 2 = 180 degrees, etc.
        if (time > 23215 || time <= 6000) {// First quad
            correctAngle = Math.abs(moonHeightVal);
        } else if (6000 < time && time <= 12785) { //second quad
            correctAngle = 1-Math.abs(moonHeightVal) + 1;
        } else if (12785 < time && time <= 18000) { //third quad
            correctAngle = Math.abs(moonHeightVal) + 2;
        } else if (18000 < time && time <= 23215) { //forth quad
            correctAngle = 1-Math.abs(moonHeightVal) + 3;
        }

        // Convert angle to both degress and radians
        double correctAngleD = correctAngle * 90;
        double correctAngleR = correctAngleD * (Math.PI/180);
        // Create a vector for the sun
        Vec3 moon = new Vec3(Math.cos(correctAngleR),Math.sin(correctAngleR), 0); // This should be correct

        if (checkMoon) {
            vector = new Vec3(-vector.xCoord, -vector.yCoord, -vector.zCoord);
        }

        double dotProd = moon.dotProduct(vector);
        double absMoon = moon.lengthVector();
        double absVector = vector.lengthVector();

        // This is the angle between the player vector and the moon
        angle = Math.acos(dotProd / (absMoon * absVector)) * (180/Math.PI);
        if (angle < threshold) {
            return true;
        }
        return false;
    }

 

I'm just going to leave this here for now, I'll probably work on it later. If you guys can make it more accurate or implement a check for looking through walls that would be amazing. But for now it works.

 

EDIT: Its inaccurate because the moon vector seems to not be exactly centred on the moon, I think its slightly above and to the left.

No signature for you!

Link to comment
Share on other sites

One thing I was wondering:

 

Minecraft is faking a dome-shaped sky over a flat world, so it makes the apogee of the sun/moon always pass directly overhead the player. That is good for purposes of the calculation required for this mod, but I'm not entirely certain whether that makes the rotation point actually at the player. It is possible below the player somewhere inside the ground.

 

If the rotation point for the sky is actually below the player, then for accurate angle you would need to know how far away the sun/moon is and use trigonometry to adjust the celestial angle relative to the player. The good news is that the trigonometry shouldn't be hard -- you can approximate the triangle as a right angle because the angle discrepancy is probably small.

 

Anyway, assuming for the moment that the sky does rotate around the player. In that case I think the code you posted is way more complicated than it needs to be.

 

I think look vector is normalized (length 1.0) and so if you create a normalized vector from the celestial angle I think if you just take the dot product of the look vector and the celestial vector, if the length of the result is close  to 1.0 then I think that means you're looking along the celestial vector.

 

That's it. Just convert celestial angle to a normalized vector, dot product with look vector and check if result is close to 1.0.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

Minecraft is faking a dome-shaped sky over a flat world, so it makes the apogee of the sun/moon always pass directly overhead the player. That is good for purposes of the calculation required for this mod, but I'm not entirely certain whether that makes the rotation point actually at the player. It is possible below the player somewhere inside the ground.

 

Its centered on the player.  It's only a fake dome.

You can see this when flying up, or rather, being blasted by TNT or teleporting into the sky thousands or even millions of blocks.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

One thing I was wondering:

 

Minecraft is faking a dome-shaped sky over a flat world, so it makes the apogee of the sun/moon always pass directly overhead the player. That is good for purposes of the calculation required for this mod, but I'm not entirely certain whether that makes the rotation point actually at the player. It is possible below the player somewhere inside the ground.

 

If the rotation point for the sky is actually below the player, then for accurate angle you would need to know how far away the sun/moon is and use trigonometry to adjust the celestial angle relative to the player. The good news is that the trigonometry shouldn't be hard -- you can approximate the triangle as a right angle because the angle discrepancy is probably small.

 

Anyway, assuming for the moment that the sky does rotate around the player. In that case I think the code you posted is way more complicated than it needs to be.

 

I think look vector is normalized (length 1.0) and so if you create a normalized vector from the celestial angle I think if you just take the dot product of the look vector and the celestial vector, if the length of the result is close  to 1.0 then I think that means you're looking along the celestial vector.

 

That's it. Just convert celestial angle to a normalized vector, dot product with look vector and check if result is close to 1.0.

 

Their position is hardcoded in RenderGlobal#renderSky and it is relative to the viewer.

& Minecraft just uses fake Celestial Sphere model.

 

@OP

It might be a problem with getLookVec and eye position, does it return the right value?

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Link to comment
Share on other sites

@OP

It might be a problem with getLookVec and eye position, does it return the right value?

 

So the code for getLookVec is this:

    /**
     * returns a (normalized) vector of where this entity is looking
     */
    public Vec3 getLookVec()
    {
        return this.getLook(1.0F);
    }

    /**
     * interpolated look vector
     */
    public Vec3 getLook(float p_70676_1_)
    {
        if (p_70676_1_ == 1.0F)
        {
            return this.getVectorForRotation(this.rotationPitch, this.rotationYawHead);
        }
        else
        {
            float f1 = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * p_70676_1_;
            float f2 = this.prevRotationYawHead + (this.rotationYawHead - this.prevRotationYawHead) * p_70676_1_;
            return this.getVectorForRotation(f1, f2);
        }
    }

    /**
     * Creates a Vec3 using the pitch and yaw of the entities rotation.
     *  
     * @param pitch The rotational pitch of the entity.
     * @param yaw The rotational yaw of the entity.
     */
    protected final Vec3 getVectorForRotation(float pitch, float yaw)
    {
        float f2 = MathHelper.cos(-yaw * 0.017453292F - (float)Math.PI);
        float f3 = MathHelper.sin(-yaw * 0.017453292F - (float)Math.PI);
        float f4 = -MathHelper.cos(-pitch * 0.017453292F);
        float f5 = MathHelper.sin(-pitch * 0.017453292F);
        return new Vec3((double)(f3 * f4), (double)f5, (double)(f2 * f4));
    }

So I'm assuming its returning the correct value. I think the error is in some part of the code on my part, and probably because getCelestialAngle() probably returns an angle centred on the top left of the sun/moon.

 

Thinking about it, is there anyway I can draw the vector in the world? I could probably use it to visualise what the vectors look like.

No signature for you!

Link to comment
Share on other sites

You can draw a vector easily.  A vector is just three values indicating the distance away from something of the "end" of the vector relative to its origin. So look up how to draw a line and then simply draw a line from player eye position to the eye position plus the vector coordinates.

 

Anyway, back to my previous post, it seems that the attempted code is much too complex. Why all the ATAN and other stuff? Just dot product the celestial angle (converted to a nomalized vector) and look vector and you're done.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

So I'm assuming its returning the correct value. I think the error is in some part of the code on my part, and probably because getCelestialAngle() probably returns an angle centred on the top left of the sun/moon.

Your code is right, and the angle is centered on the center of sun and moon.

It might be rendering offset problem of minecraft.;

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Link to comment
Share on other sites

Anyway, try drawing a dot on the position you get using TickEvent.RenderTickEvent, and compare that with sun position.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Link to comment
Share on other sites

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...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

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