
player_sprint = {}

local pl = {}

function player_sprint.to_walk(player)
  if not pl[player] then pl[player] = {
    is_sprinting = false,
    is_sneaking = false
  } end
  playerphysics.remove_physics_factor(player, "speed", "player_sprint")
  pl[player].is_sprinting = false
  pmb_util.unset_fov(player, "player_sprint")
end

local function sneak_allowed(player)
  local node = minetest.get_node(player:get_pos())
  local ndef = minetest.registered_nodes[node.name]
  if ndef.climbable then return false end
  return true
end

function player_sprint.on_step(dtime)
  for _, player in pairs(minetest.get_connected_players()) do

    local ct = player_info.get(player)
    if not ct then return end

    if pl[player].is_sprinting and not ct.can_sprint then
      player_sprint.to_walk(player)
    end

    if ct.is_sneaking and sneak_allowed(player) and not pl[player].is_sneaking then
      playerphysics.add_physics_factor(player, "speed", "player_sprint:sneak", 0.6)
      pl[player].is_sneaking = true
    elseif (not ct.is_sneaking) and pl[player].is_sneaking then
      playerphysics.remove_physics_factor(player, "speed", "player_sprint:sneak")
      pl[player].is_sneaking = false
    end

    if ct.can_sprint and (ct.just_pressed.aux1 or ct.just_pressed.up
     or ct.just_released.aux1 or ct.just_released.up) then
      if (not pl[player].is_sprinting) and ct.ctrl.up and ct.ctrl.aux1 and ct.can_sprint then
        playerphysics.add_physics_factor(player, "speed", "player_sprint", 1.5)
        pl[player].is_sprinting = true
        pmb_util.set_fov(player, {
            tag = "player_sprint",
            fov = 1.07,
            is_multiplier = true,
            transition_time = 0.1 })
      elseif pl[player].is_sprinting then
        player_sprint.to_walk(player)
      end
    end
  end
end

minetest.register_on_dieplayer(player_sprint.to_walk)
minetest.register_on_joinplayer(player_sprint.to_walk)

minetest.register_globalstep(player_sprint.on_step)
