When trying to use command blocks to detect when a player leaves a square area by detecting them with circles that have very large radii surrounding the area, I discovered very weird results when the player is farther than 46340 blocks from the centre of the detection radius.
This issue seems to be related to the limitation of the INT data type and how the player's location is calculated because player detection becomes inverted when the square of the radius is grater than 2,147,483,647
I've attached a world save with an example of this issue using a command block with the command:
testfor @a[46340,0,0,1]
Linked issues
Attachments
Comments 6
I don't think it's a short type because the player's xyz coordinates have to be squared if it is using an Euclidean formula. Now, I haven't seen at the actual code, nor do I know Java's syntax very well, but I think it could be something like this:
int displacementX = playerX - selectorX;
int displacementY = playerY - selectorY;
int displacementZ = playerZ - selectorZ;
// =============================
int squaredDisX = Math.pow(displacementX,2);
int squaredDisY = Math.pow(displacementY,2);
int squaredDisZ = Math.pow(displacementZ,2);
int squaredSum = squaredDisX + squaredDisY +squaredDisZ;
// =============================
int calculatedRadius = sqrt(squaredSum);
if (selectorR < calculatedRadius < selectorRM) {
playerDetected() //do something
}
If the player's x and y displacement are 0 and their z displacement is 46341, the squaredDisZ would be -2147479015 because of the overflow. After square-root, the calculated radius would be equal to NaN. This continues until the players radius is greater than 65536 when the overflowed value becomes greater than 0.
I think this issue can be fixed if the "squaredDisX", "squaredDisZ" and, "squaredSum" were declared as long instead of int. This would expand the maximum radius to 3,037,000,499; about 100 times the radius of the playable Minecraft map.
I've dug through the decompiled code and found the bug, Cole is correct.
Here is the code that was wrong, fixed:
ChunkCoordinates.java
public float getDistanceSquared(int par1, int par2, int par3)
{
long var4 = this.posX - par1;
long var5 = this.posY - par2;
long var6 = this.posZ - par3;
return (float)(var4 * var4 + var5 * var5 + var6 * var6);
}
There now seems to be a check for if the player is farther than 46340 that the command always returns false in 1.6.2
The detection overflow pattern is still present with the rm
variable.
eg. Using these commands in the chat:
/say @p[rm=0]
/say @p[rm=1]
/say @p[rm=46340]
/say @p[rm=46341]
/say @p[rm=65536]
/say @p[rm=65537]
Is this still a concern in the current Minecraft version? If so, please update the affected versions in order to best aid Mojang ensuring bugs are still valid in the latest releases/pre-releases. If this has been done, we can reopen the issue.
Keep in mind that the "Resolved"-Status on this ticket just means "Answered", and that we are waiting for further information on whether this issue still exists or not. We will reopen it as soon as the requested information has been deliviered.
46340 is SQRT(2) * 32767, so maybe there is a short int somewhere in between...