Skip to content

Inconsistent rounding with position at negative y levels (y < 0) #16809

@fnetX

Description

@fnetX

Luanti version

(Flatpak release)
Luanti 5.14.0 (Linux)
Using LuaJIT 2.1.1756211046 (OpenResty)
Built by GCC 15.2
Running on Linux/6.12.57 x86_64
BUILD_TYPE=Release
RUN_IN_PLACE=0
USE_CURL=1
USE_GETTEXT=1
USE_SOUND=1
STATIC_SHAREDIR="/app/share/luanti"
STATIC_LOCALEDIR="/app/share/locale"

Operating system and version

Linux Mint Debian Edition 7 (based on Debian 13)

CPU model

Intel Core i7-5650U

GPU model

No response

Active renderer

No response

Summary

Naive calculations based on player position seem to suffer from rounding errors. I'd expect the following code to provide the node below the player:

pos = player:get_pos()
pos.y = pos.y - 1
n =  core.get_node(pos)

However, it does not work reliably when y < 0. While this can probably be worked around, it seems that several mods suffer from this problem and the behaviour is confusing, to say the least. I am not sure if it can be fixed in the engine, but I think there should be a canonical way to do such calculations, and I found nothing related to this in the docs.

Background and use case

I was investigating that several mods don't work properly on my server. TNT run and sumo minigames sometimes don't kill players or let TNT fall.

Upon investigation, I also found that other mods like worldedit are not consistent: The behaviour of which node is selected differs based on the y value. I recorded a demonstration in which I additionally demonstrate that the selected node is not even deterministic based on the node I stand on. If I fly, go down slightly, and disable fly, I can trigger that I'm apparently on a different level. See demonstration video:

we-node-glitch.webm

Steps to reproduce

I created a demonstration world and a simple mod that demonstrates the behaviour.

init.lua:

core.register_on_joinplayer(function(player, last_login) checkfn(player) end)

function checkfn(player)
	pos = player:get_pos()
	pos_get = pos
	pos_get.y = pos_get.y - 1
	node_name = core.get_node(pos_get).name
	core.chat_send_all("y: " .. tostring(pos.y) .. ", below is: " .. node_name)
	core.after(1, function() checkfn(player) end)
end

mod and world are attached. I recorded another video (with audio comments):

posglitch.webm

Likely related

#6818
#1154
#14757

Metadata

Metadata

Assignees

No one assigned

    Labels

    @ DocumentationImprovements or additions to documentation@ Script APIBugIssues that were confirmed to be a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions