hook.Add("PlayerBindPress", "Keypad_ButtonPad", function(ply, bind, pressed)
	if !pressed then return end
	local eyepos = ply:EyePos()
	local tr = util.TraceLine({
		start = eyepos,
		endpos = eyepos + ply:GetAimVector() * 65,
		filter = ply
	})
	local ent = tr.Entity
	if !IsValid(ent) or !ent.IsKeypad then return end
	if string.find(bind, "+use", nil, true) then
		local element = ent:GetHoveredElement()
		if !element or !element.click then return end
		element.click(ent)
	end
end)

local physical_keypad_commands = {
	[KEY_ENTER] = function(self)
		self:SendCommand(self.Command_Accept)
	end,
	[KEY_PAD_ENTER] = function(self)
		self:SendCommand(self.Command_Accept)
	end,
	[KEY_PAD_MINUS] = function(self)
		self:SendCommand(self.Command_Abort)
	end,
	[KEY_PAD_PLUS] = function(self)
		self:SendCommand(self.Command_Abort)
	end
}

for i = KEY_PAD_1, KEY_PAD_9 do
	physical_keypad_commands[i] = function(self)
		self:SendCommand(self.Command_Enter, i - KEY_PAD_1 + 1)
	end
end

local last_press = 0
local enter_strict = CreateConVar("keypad_enter_strict", 0, FCVAR_ARCHIVE, "Only allow the numpad's enter key to be used to accept keypads' input")
hook.Add("PlayerButtonDown", "Keypad_ButtonPad", function(ply, button)
	if !IsFirstTimePredicted() then return end
	local realtime = RealTime()
	if realtime - 0.1 < last_press then return end
	local pressed = physical_keypad_commands[button]
	if pressed then
		if enter_strict:GetBool() and button == KEY_ENTER then return end
		local eyepos = ply:EyePos()
		local tr = util.TraceLine({
			start = eyepos,
			endpos = eyepos + ply:GetAimVector() * 65,
			filter = ply
		})
		local ent = tr.Entity
		if !IsValid(ent) or !ent.IsKeypad then return end
		last_press = realtime
		pressed(ent)
	end
end)