local function springboard_formspec(x, y, z)
   local formspec =
   'formspec_version[3]'..
   'size[8,6]'..
   'textarea[.5,.5;7,2;;;Set the springiness here. A player will be boosted when the spring releases. (1 second after punching the node.) Directions are world based, and do not correlate to the direction the node is positioned or player orientation. Play around with the values to find something you like.]'..
   'field[1,3;2,.5;x;X: (-10 - 10);'..x..']'..
   'field[1,4;2,.5;y;Y: (7 - 25);'..y..']'..
   'field[1,5;2,.5;z;Z: (-10 - 10);'..z..']'..
   'button_exit[5,5;2,.5;save;Submit]'
   return formspec
end

local function math_clamp(val, lower, upper)
   if not lobby.is_integer(val) then
      val = 0
   end
   return math.max(lower, math.min(upper, val))
end

minetest.register_on_player_receive_fields(function(player, formname, fields)
   local name = player:get_player_name()
   if formname == 'platformer:springboard' then
      if fields.save then
         local pos = tasks.player_config[name]
         local meta = minetest.get_meta(pos)
         local vel_x = math_clamp(fields.x, -10,10)
         local vel_y = math_clamp(fields.y, 7,25)
         local vel_z = math_clamp(fields.z, -10,10)
         meta:set_string('x', vel_x)
         meta:set_string('y', vel_y)
         meta:set_string('z', vel_z)
      end
   end
end)

minetest.register_node('platformer:springboard_sprung', {
   description = 'Springboard',
   drawtype = 'mesh',
   mesh = 'platformer_spring_sprung.obj',
   tiles = {'platformer_spring_sprung.png'},
   paramtype = 'light',
   paramtype2 = 'facedir',
   groups = {breakable=1},
   on_construct = function(pos)
      local meta = minetest.get_meta(pos)
      meta:set_string('x', 0)
      meta:set_string('y', 7)
      meta:set_string('z', 0)
   end,
   on_punch = function(pos, node)
      local timer = minetest.get_node_timer(pos)
      minetest.swap_node(pos, {name = 'platformer:springboard_loaded', param2 = node.param2})
      timer:start(1)
   end,
   on_rightclick = function(pos, node, clicker, itemstack)
      local item = itemstack:get_name()
      local name = clicker:get_player_name()
      if item == 'tasks:configurator' then
         if not minetest.is_protected(pos, name) or minetest.check_player_privs(name, {server = true}) then
            tasks.player_config[name] = pos
            local meta = minetest.get_meta(pos)
            local x_vel = meta:get_string('x')
            local y_vel = meta:get_string('y')
            local z_vel = meta:get_string('z')
            minetest.show_formspec(name, 'platformer:springboard', springboard_formspec(x_vel, y_vel, z_vel))
         end
      end
   end,
})

minetest.register_node('platformer:springboard_loaded', {
   description = 'Springboard',
   drawtype = 'mesh',
   mesh = 'platformer_spring_loaded.obj',
   tiles = {'platformer_spring_loaded.png'},
   paramtype = 'light',
   paramtype2 = 'facedir',
   selection_box = {type = 'fixed',
      fixed = {
         {-.5, -.5, -.5, .5, 0, .5},}},
   collision_box = {type = 'fixed',
      fixed = {
         {-.5, -.5, -.5, .5, 0, .5},}},
   groups = {breakable=1, not_in_creative_inventory=1},
   drop = 'platformer:springboard_sprung',
   on_timer = function(pos)
      local objs = minetest.get_objects_inside_radius(pos, .8)
      for _, obj in pairs(objs) do
         if obj:is_player() then
            local meta = minetest.get_meta(pos)
            local x_vel = tonumber(meta:get_string('x')) or 0
            local y_vel = tonumber(meta:get_string('y')) or 0
            local z_vel = tonumber(meta:get_string('z')) or 0
            obj:add_velocity({x=x_vel, y=y_vel, z=z_vel})
         end
      end
      local node = minetest.get_node(pos)
      minetest.swap_node(pos, {name = 'platformer:springboard_sprung', param2 = node.param2})
      minetest.sound_play('platformer_spring_launch', {pos = pos, gain = 2, max_hear_distance = 14})
   end
})
