Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A way to detect when a player jumps #9631

Closed
Zughy opened this issue Apr 10, 2020 · 8 comments
Closed

A way to detect when a player jumps #9631

Zughy opened this issue Apr 10, 2020 · 8 comments
Labels
Feature request Issues that request the addition or enhancement of a feature Non-trivial A large amount of work is required to address this (sometimes to the point of being infeasible). Possible close @ Script API Won't add The feature request was rejected and will not be added.

Comments

@Zughy
Copy link
Member

Zughy commented Apr 10, 2020

Problem

There doesn't seem to be any detection for when the player jumps. I tried checking the block beneath if it's equal to air on minetest.register_globalstep, but it gets called several times if I don't put some sort of boolean, adding unnecessary weight to the code. And, even if there is an easier way to do it, it doesn't seem intuitive for me at all (I checked both in the dev wiki and in the txt file)

Solutions

Player:is_on_air() (or is on ground, floor, or minetest.is_player_on_air(player) etc., whatever) like Godot does with is_on_floor(). Maybe checking if the collision box is actually colliding with something (idk how it works the C++ builtin part, sorry)
EDIT by paramat: See lua code posted in #9631 (comment)
The issue author is actually trying to detect when a player jumps, which is very different to detecting "air" below a player.

Additional info

It looks like back in 2017 something asked about something pretty similar already without any answer, idk if it can help https://forum.minetest.net/viewtopic.php?f=47&t=17646

@Zughy Zughy added the Feature request Issues that request the addition or enhancement of a feature label Apr 10, 2020
@Andrey2470T
Copy link
Contributor

Andrey2470T commented Apr 10, 2020

Actually, yes, there are no any API ways to check what nodes are beneath, except a workaround (calculate a position of the player bottom and retrieving the node by minetest.get_node at each step).

I think it would be nice to get info about colliding result with other ones along to each global axle. Maybe is it a worth to add a callback like e.g. 'after_collide' for entity and node which a collision result table is passed to?

@sorcerykid
Copy link
Contributor

Part of the reason this will be rather difficult to implement iirc, is because player physics are handled client-side. So that would require the server duplicate the calculations for player motion just to provide an API for scripts to check whether the player is in air, which is extremely infrequent. Now in fairness, I could be mistaken. I know there is cheat-detection code which likely performs these calculations anyway. So hopefully a core-dev can better clarify the technicalities.

@paramat
Copy link
Contributor

paramat commented Apr 10, 2020

It seems easy to implement, but would of course be serverside so slightly out of sync with what the player is doing clientside, depending on network delay.
I do not think the issue author is requesting this be clientside and instantly responsive.
So it seems this is a request for an API that just checks the node below for being "air", or perhaps "airlike" drawtype.
Would it be much faster being an API, relative to using 'get_node' in Lua?

@paramat
Copy link
Contributor

paramat commented Apr 10, 2020

I tried checking the block beneath if it's equal to air on minetest.register_globalstep, but it gets called several times if I don't put some sort of boolean, adding unnecessary weight to the code

You need to code this to only check every few globalsteps, not every globalstep.
Checking 1 node is lightweight code, so i do not understand the complaint of intensive code.
If the API exists you would have to run the check just as frequently. As an API it might be a little faster but not significantly.
So am i right in assuming you are requesting this purely for the convenience of not coding it in Lua?

@SmallJoker
Copy link
Member

SmallJoker commented Apr 11, 2020

Duplicate of #3918

EDIT: Not directly duplicate: This issue is not about a callback, and limited to Y+ collisions.
Not as generic as the other request, but would be faster approach due to limited callback frequency.

Please note that even the client doesn't know whether it's standing on ground. For example: #1460 and the obscure #6959.

@SmallJoker SmallJoker marked this as a duplicate of #3918 Apr 11, 2020
@SmallJoker SmallJoker reopened this Apr 11, 2020
@Zughy
Copy link
Member Author

Zughy commented Apr 11, 2020

You need to code this to only check every few globalsteps, not every globalstep.
Checking 1 node is lightweight code, so i do not understand the complaint of intensive code.
So am i right in assuming you are requesting this purely for the convenience of not coding it in Lua?

Yes, because I stated before

even if there is an easier way to do it, it doesn't seem intuitive for me at all

I don't want to disrespect anyone's job because I honestly think what you're all doing is amazing and also because being a developer is not my job nor I studied for it, but info are scattered in at least three different sites and I often find myself going full trial and error to understand how something exactly works, it's... frustrating. So in short yes, I don't know how to reproduce it on Lua and I think it'd help a lot of people having about my same level of knowledge

@Zughy
Copy link
Member Author

Zughy commented Apr 12, 2020

This was my take in Lua by the way:

local players_jumping = {} --KEY: player, VALUE: boolean

minetest.register_globalstep(function(dtime)

  for pl_name, bool in pairs(players_jumping) do

    local pl = minetest.get_player_by_name(pl_name)

    if pl:get_player_control().jump and pl:get_hp() > 0 and not players_jumping[pl_name] then

      local pos = pl:get_pos()
      local pos_feet = {x = pos.x, y = pos.y-0.501, z = pos.z}
      local drawtype = minetest.registered_nodes[minetest.get_node(pos_feet).name]["drawtype"]

      if drawtype ~= "normal" and drawtype ~= "glasslike" and drawtype ~= "nodebox" then return end
      players_jumping[pl_name] = true

      --DO STUFF

      minetest.after(0.2, function()
        players_jumping[pl_name] = false
      end)
    end

  end
end)

There are still two consistent issues with the code:

  1. if I stand on the edge of a block enough to have my feet floating on air, it won't be triggered because the block beneath my feet is indeed air. Have I to check every corner of the colliding box? Is it even possible via Lua?
  2. if I consequently jump as in "climbing" a Y +1 steep, the second jump won't trigger the sound

That is, of course, if my method isn't plain wrong

@paramat paramat changed the title Player:is_on_air() A way to detect when a player jumps Oct 1, 2020
@paramat paramat added Non-trivial A large amount of work is required to address this (sometimes to the point of being infeasible). No core dev support long term Possible close labels Oct 1, 2020
@Zughy
Copy link
Member Author

Zughy commented Oct 23, 2020

Sparing work to core devs, according to labels

@Zughy Zughy closed this as completed Oct 23, 2020
@rubenwardy rubenwardy added Won't add The feature request was rejected and will not be added. and removed No core dev support long term labels May 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature request Issues that request the addition or enhancement of a feature Non-trivial A large amount of work is required to address this (sometimes to the point of being infeasible). Possible close @ Script API Won't add The feature request was rejected and will not be added.
Projects
None yet
Development

No branches or pull requests

6 participants