# [1.7.10] Detect if player is looking at the sun.

## Recommended Posts

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!

##### Share on other sites

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.

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

##### Share on other sites

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.

##### Share on other sites

I personally wouldn't much math. I'd just simply record the rotation pitch and yaw of the player at set time intervals and look those up. Depending on the resolution/error allowed, you might only need like 24 data points.

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

##### Share on other sites

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.

##### Share on other sites

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!

##### Share on other sites

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/

##### Share on other sites

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.

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.

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

×   Pasted as rich text.   Restore formatting

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

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

• ### Posts

• I'm willing to do a mod collab with someone if you want to reply! We can agree what time, version.
• I found it. It's the IForgeEntity#getStepHeight()
• Hello everyone, I'm struggling with a weird issue, I'm trying to make a server pack for a new modpack and sometime I can join the server but got immediately disconnected with the message below: I've seen seen other posts with the same error but nobody mention how they fix it (if they really fixed it).   Issue: Here is the weird part, I have two scenarios occuring : I start my client, join the server, everything is fine. I can disconnect/reconnect to the server. It works. I start my client, join the server, get disconnected with the message above. If I try to reconnect, I will always get the same error. I must restart the client and hope this time it will works.   Additional informations: I have tried with Forge 43.2.0, 43.3.0 (stable) and 43.3.5 (latest) on both server and client with the same results. The server pack is created using ServerPackCreator. There is no problem in single player mode. I can't determine if this could be a mod or a Forge issue. I suspect there is somewhere an unstable loading order that could explain that problem. I can't find anything of interest in the server and client debug.log (or I don't know what to look for).   Logs: Client (debug.log): https://mclo.gs/4jf8lz7 Server (debug.log): https://mclo.gs/aT3hgEG Any help or hint to find the culprit appreciated . Thanks for reading

• ### Who's Online (See full list)

×

• #### Activity

×
• Create New...