Jump to content

Recommended Posts

Posted

Hello everyone,

 

I'm about to undertake trying to detect whether or not the player is looking at the sun, within a certain degree of error. I want to spitball my ideas with all of you before I attempt to implement this, in case there's a much better way to do this or someone has already implemented it.

 

My idea: using player.rotationPitch and rotationYaw, I can relatively easily correlate their look direction with the current time of day, obtained by player.worldObj.getWorldTime() % 24000. Experimentation will let me figure out what angles fit nicely with what times. I'm sure I could find something precise by looking at the render code for the actual sun's movement, but I honestly think it would take me longer to figure that one out than whip up some tables. I'm still not entirely sure if this is altitude-dependent or not.

 

Next, I haven't really looked into it too much yet, but I think there's decent support for ray-tracing/getting the block the player is looking at. Basically, I need to make sure that the sun isn't obscured by a non-transparent block. Is this efficient/possible? This is the part I don't know how to do yet.

 

Some obvious problems: if the player is underground in an enormous cave, the sun will still show up. Hence, it will probably be considered visible to them. But this is such an edge-case that I think I'd be fine just dealing with it.

 

Has anyone else tried this? Does anyone have suggestions?

 

Thanks!

Posted

There's already a function that converts worldTime into a sun angle.  Ah here,

world.getCelestialAngle(0)

.  The 0 is a time offset, so passing 0 means "right now" and passing 6000 would mean "the height 6000 ticks from now."  The returned value is an angle (in degrees, iirc).

 

I'm using it like this:

float sunHeightVal = (float)Math.sin((event.world.getCelestialAngle(0)+0.25f)*2*Math.PI);

As I'm interested in knowing how high in the sky the sun is.  The

+0.25

is needed as getCelestialAngle actually subtracts a quarter of a rotation out (see WorldProvider line 102), then I convert to radians and Math.sin that.

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.

Posted

Note that just throwing 6000 to the parameter would break some custom dimension mods.

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

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

Posted

There's already a function that converts worldTime into a sun angle.  Ah here,

world.getCelestialAngle(0)

.  The 0 is a time offset, so passing 0 means "right now" and passing 6000 would mean "the height 6000 ticks from now."  The returned value is an angle (in degrees, iirc).

 

I'm using it like this:

float sunHeightVal = (float)Math.sin((event.world.getCelestialAngle(0)+0.25f)*2*Math.PI);

As I'm interested in knowing how high in the sky the sun is.  The

+0.25

is needed as getCelestialAngle actually subtracts a quarter of a rotation out (see WorldProvider line 102), then I convert to radians and Math.sin that.

 

Thanks for the tip! I'm gonna give this a shot tonight and get back to you guys.

Posted

Hey again everyone, sorry it's been so long. Life got in the way of modding a bit.

But here we go again, new problems. I'm now able to determine if the player has the correct rotation to be viewing the sun, which is great. Issue is, now I need to make sure they can actually see the sun. I'm trying to accomplish this through raytracing. I found this really useful piece of code on Jabelar's blog.

 

MovingObjectPosition mop = Minecraft.getMinecraft().renderViewEntity.rayTrace(200, 1.0F);
if(mop != null)
{
    Block blockLookingAt = worldObj.getBlock(mop.blockX, mop.blockY, mop.blockZ) ; 
}

 

Checking if the player is rotated towards the sun and that blockLookingAt is air is almost there. The only issue is transparent blocks: I want the player to be able to see the sun through glass, leaves, etc.

 

So my question now, is there a way I can raytrace while ignoring certain blocks? Ex: if the trace encounters glass, pretend it didn't and keep on going?

 

Thanks!

Posted

So my question now, is there a way I can raytrace while ignoring certain blocks? Ex: if the trace encounters glass, pretend it didn't and keep on going?

 

I don't see a version of ray trace that does that, although the world ray trace function does have a flag for tracing through liquids.

 

I think you'd need to create your own raytrace by copying the vanilla code for that method and modifying it to ignore blocks. It looks possible. The ray trace method basically just calls this function in World:

 

    public MovingObjectPosition func_147447_a(Vec3 p_147447_1_, Vec3 p_147447_2_, boolean p_147447_3_, boolean p_147447_4_, boolean p_147447_5_)

    {

        if (!Double.isNaN(p_147447_1_.xCoord) && !Double.isNaN(p_147447_1_.yCoord) && !Double.isNaN(p_147447_1_.zCoord))

        {

            if (!Double.isNaN(p_147447_2_.xCoord) && !Double.isNaN(p_147447_2_.yCoord) && !Double.isNaN(p_147447_2_.zCoord))

            {

                int i = MathHelper.floor_double(p_147447_2_.xCoord);

                int j = MathHelper.floor_double(p_147447_2_.yCoord);

                int k = MathHelper.floor_double(p_147447_2_.zCoord);

                int l = MathHelper.floor_double(p_147447_1_.xCoord);

                int i1 = MathHelper.floor_double(p_147447_1_.yCoord);

                int j1 = MathHelper.floor_double(p_147447_1_.zCoord);

                Block block = this.getBlock(l, i1, j1);

                int k1 = this.getBlockMetadata(l, i1, j1);

 

                if ((!p_147447_4_ || block.getCollisionBoundingBoxFromPool(this, l, i1, j1) != null) && block.canCollideCheck(k1, p_147447_3_))

                {

                    MovingObjectPosition movingobjectposition = block.collisionRayTrace(this, l, i1, j1, p_147447_1_, p_147447_2_);

 

                    if (movingobjectposition != null)

                    {

                        return movingobjectposition;

                    }

                }

 

                MovingObjectPosition movingobjectposition2 = null;

                k1 = 200;

 

                while (k1-- >= 0)

                {

                    if (Double.isNaN(p_147447_1_.xCoord) || Double.isNaN(p_147447_1_.yCoord) || Double.isNaN(p_147447_1_.zCoord))

                    {

                        return null;

                    }

 

                    if (l == i && i1 == j && j1 == k)

                    {

                        return p_147447_5_ ? movingobjectposition2 : null;

                    }

 

                    boolean flag6 = true;

                    boolean flag3 = true;

                    boolean flag4 = true;

                    double d0 = 999.0D;

                    double d1 = 999.0D;

                    double d2 = 999.0D;

 

                    if (i > l)

                    {

                        d0 = (double)l + 1.0D;

                    }

                    else if (i < l)

                    {

                        d0 = (double)l + 0.0D;

                    }

                    else

                    {

                        flag6 = false;

                    }

 

                    if (j > i1)

                    {

                        d1 = (double)i1 + 1.0D;

                    }

                    else if (j < i1)

                    {

                        d1 = (double)i1 + 0.0D;

                    }

                    else

                    {

                        flag3 = false;

                    }

 

                    if (k > j1)

                    {

                        d2 = (double)j1 + 1.0D;

                    }

                    else if (k < j1)

                    {

                        d2 = (double)j1 + 0.0D;

                    }

                    else

                    {

                        flag4 = false;

                    }

 

                    double d3 = 999.0D;

                    double d4 = 999.0D;

                    double d5 = 999.0D;

                    double d6 = p_147447_2_.xCoord - p_147447_1_.xCoord;

                    double d7 = p_147447_2_.yCoord - p_147447_1_.yCoord;

                    double d8 = p_147447_2_.zCoord - p_147447_1_.zCoord;

 

                    if (flag6)

                    {

                        d3 = (d0 - p_147447_1_.xCoord) / d6;

                    }

 

                    if (flag3)

                    {

                        d4 = (d1 - p_147447_1_.yCoord) / d7;

                    }

 

                    if (flag4)

                    {

                        d5 = (d2 - p_147447_1_.zCoord) / d8;

                    }

 

                    boolean flag5 = false;

                    byte b0;

 

                    if (d3 < d4 && d3 < d5)

                    {

                        if (i > l)

                        {

                            b0 = 4;

                        }

                        else

                        {

                            b0 = 5;

                        }

 

                        p_147447_1_.xCoord = d0;

                        p_147447_1_.yCoord += d7 * d3;

                        p_147447_1_.zCoord += d8 * d3;

                    }

                    else if (d4 < d5)

                    {

                        if (j > i1)

                        {

                            b0 = 0;

                        }

                        else

                        {

                            b0 = 1;

                        }

 

                        p_147447_1_.xCoord += d6 * d4;

                        p_147447_1_.yCoord = d1;

                        p_147447_1_.zCoord += d8 * d4;

                    }

                    else

                    {

                        if (k > j1)

                        {

                            b0 = 2;

                        }

                        else

                        {

                            b0 = 3;

                        }

 

                        p_147447_1_.xCoord += d6 * d5;

                        p_147447_1_.yCoord += d7 * d5;

                        p_147447_1_.zCoord = d2;

                    }

 

                    Vec3 vec32 = Vec3.createVectorHelper(p_147447_1_.xCoord, p_147447_1_.yCoord, p_147447_1_.zCoord);

                    l = (int)(vec32.xCoord = (double)MathHelper.floor_double(p_147447_1_.xCoord));

 

                    if (b0 == 5)

                    {

                        --l;

                        ++vec32.xCoord;

                    }

 

                    i1 = (int)(vec32.yCoord = (double)MathHelper.floor_double(p_147447_1_.yCoord));

 

                    if (b0 == 1)

                    {

                        --i1;

                        ++vec32.yCoord;

                    }

 

                    j1 = (int)(vec32.zCoord = (double)MathHelper.floor_double(p_147447_1_.zCoord));

 

                    if (b0 == 3)

                    {

                        --j1;

                        ++vec32.zCoord;

                    }

 

                    Block block1 = this.getBlock(l, i1, j1);

                    int l1 = this.getBlockMetadata(l, i1, j1);

 

                    if (!p_147447_4_ || block1.getCollisionBoundingBoxFromPool(this, l, i1, j1) != null)

                    {

                        if (block1.canCollideCheck(l1, p_147447_3_))

                        {

                            MovingObjectPosition movingobjectposition1 = block1.collisionRayTrace(this, l, i1, j1, p_147447_1_, p_147447_2_);

 

                            if (movingobjectposition1 != null)

                            {

                                return movingobjectposition1;

                            }

                        }

                        else

                        {

                            movingobjectposition2 = new MovingObjectPosition(l, i1, j1, b0, p_147447_1_, false);

                        }

                    }

                }

 

                return p_147447_5_ ? movingobjectposition2 : null;

            }

            else

            {

                return null;

            }

        }

        else

        {

            return null;

        }

    }

 

 

So I would just copy that and go through it to make sure you understand it (I usually refactor/rename the fields so it is easier to read, as I learn what each field does) and then the modification necessary should be pretty obvious. The liquids flag is probably instructive as it performs a similar function (i.e. ignore liquid blocks).

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

Posted

There's a function in the Block class that for the longest time had two parameters, one of which no one had any idea what it did.  That parameter was a boolean which was only ever "true" when the player right-clicked with a boat and which water used to go "raytace me!"

 

I java-doc'd it through MCP once, but I think in the 1.6 -> 1.7 update that got lost.

 

Ah, no, it's still there.

 

Block#canCollideCheck(...)

 

Anyway, you'd want to wholesale replicate World's

public MovingObjectPosition func_147447_a

and just replace the call for Block#canCollideCheck(...) with Block#isOpaqueCube()

 

There might be some edge cases where it doesn't return what you would like (e.g. a chest will return false, but ostensibly would block the user's view), but it'll be damn close.  If you want something more accurate, you'll likely have to code it yourself.

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.

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.