```lua
-- Серверный Скрипт: lua/autorun/server/notification_server.lua
if SERVER then
    util.AddNetworkString("ShowNotification")
    -- Константы
    local DEFAULT_MODEL = "models/player/alyx.mdl"
    local VALID_MODEL_PREFIX = "^models/"
    -- Белый список моделей (дополните по необходимости)
    local WHITELISTED_MODELS = {
        ["models/player/alyx.mdl"] = true,
        ["models/player/kleiner.mdl"] = true,
        ["models/player/mossman.mdl"] = true,
    }

    -- Добавьте больше разрешённых моделей здесь
    -- Вспомогательная функция для отправки сообщений источнику
    local function NotifySender(ply, message)
        if IsValid(ply) then
            ply:ChatPrint(message)
        else
            print(message)
        end
    end

    -- Функция для отправки уведомления игроку
    local function SendNotification(ply, text, modelPath)
        net.Start("ShowNotification")
        net.WriteString(text)
        net.WriteString(modelPath)
        net.Send(ply)
    end

    -- Функция для проверки формата Steam ID
    local function IsValidSteamID(sid)
        return string.match(sid, "^STEAM_[0-5]:%d:%d+$") ~= nil
    end

    -- Функция для проверки, находится ли модель в белом списке
    local function IsWhitelistedModel(modelPath)
        return WHITELISTED_MODELS[modelPath] or false
    end

    -- Консольная команда для отправки уведомлений
    -- Использование: show_notification_server <steam_id> <текст> [<путь_к_модели>]
    concommand.Add("show_notification_server", function(ply, cmd, args)
        -- Проверка прав администратора, если команда выполняется игроком
        if IsValid(ply) and not ply:IsAdmin() then
            ply:ChatPrint("У вас нет прав для использования этой команды.")
            return
        end

        -- Минимальное количество аргументов: Steam ID и текст
        if #args < 2 then
            local usageMsg = "Использование: show_notification_server <steam_id> <текст> [<путь_к_модели>]"
            NotifySender(ply, usageMsg)
            return
        end

        local steamID = args[1]
        -- Проверка формата Steam ID
        if not IsValidSteamID(steamID) then
            local errorMsg = "Неверный формат Steam ID. Пример: STEAM_0:1:123456"
            NotifySender(ply, errorMsg)
            return
        end

        -- Извлечение текста и опционального пути к модели
        table.remove(args, 1) -- Удаляем Steam ID из args
        local model = DEFAULT_MODEL
        -- Проверяем, является ли последний аргумент путём к модели
        if string.find(args[#args], VALID_MODEL_PREFIX) then
            local potentialModel = args[#args]
            if IsWhitelistedModel(potentialModel) then
                model = potentialModel
            else
                local warnMsg = "Указанная модель не разрешена. Используется модель по умолчанию."
                NotifySender(ply, warnMsg)
            end

            table.remove(args, #args)
        end

        local text = table.concat(args, " ")
        -- Находим игрока по Steam ID
        local target = player.GetBySteamID(steamID)
        if target and target:IsValid() and target:IsConnected() then
            SendNotification(target, text, model)
            local successMsg = "Уведомление отправлено игроку " .. target:Nick()
            NotifySender(ply, successMsg)
        else
            local notFoundMsg = "Игрок с Steam ID \"" .. steamID .. "\" не найден или не онлайн."
            NotifySender(ply, notFoundMsg)
        end
    end)
end
```
```lua
-- Клиентский Скрипт: lua/autorun/client/notification_client.lua
if CLIENT then
    -- Константы
    local NOTIFICATION_WIDTH, NOTIFICATION_HEIGHT = 300, 100
    local ANIMATION_DURATION = 0.5 -- секунды
    local DISPLAY_DURATION = 5 -- секунды
    local DEFAULT_MODEL = "models/player/kleiner.mdl"
    local NOTIFICATION_BG_COLOR = Color(50, 50, 50, 200)
    local TEXT_COLOR = Color(255, 255, 255)
    -- Очередь уведомлений и флаг отображения
    local notificationQueue = {}
    local isNotificationShowing = false
    -- Функция для получения позиций уведомления
    local function GetNotificationPositions()
        return {
            startX = ScrW(), -- Начальная позиция (за правым краем экрана)
            endX = ScrW() - NOTIFICATION_WIDTH - 10, -- Конечная позиция с отступом 10 пикселей от правого края
            y = ScrH() / 2 - (NOTIFICATION_HEIGHT / 2) -- Центрирование по вертикали
        }
    end

    -- Проверка валидности пути к модели
    local function IsValidModelPath(modelPath)
        return util.IsValidModel(modelPath)
    end

    -- Удаление фрейма
    local function RemoveFrame(frame)
        if IsValid(frame) then frame:Remove() end
    end

    -- Настройка панели модели
    local function SetupModelPanel(frame, modelPath)
        local mdl = vgui.Create("DModelPanel", frame)
        mdl:SetPos(10, 10)
        mdl:SetSize(80, 80)
        mdl:SetModel(IsValidModelPath(modelPath) and modelPath or DEFAULT_MODEL)
        -- Проверка валидности модели
        if not IsValid(mdl.Entity) or mdl.Entity:GetModel() ~= (IsValidModelPath(modelPath) and modelPath or DEFAULT_MODEL) then mdl:SetModel(DEFAULT_MODEL) end
        local min, max = mdl.Entity:GetRenderBounds()
        local size = math.max(max.x - min.x, max.y - min.y, max.z - min.z)
        mdl:SetFOV(45)
        mdl:SetCamPos(Vector(size, size, size))
        mdl:SetLookAt((min + max) * 0.5)
        -- Вращение модели
        function mdl:LayoutEntity(entity)
            entity:SetAngles(Angle(0, CurTime() * 30, 0))
        end
    end

    -- Настройка текстового лейбла
    local function SetupTextLabel(frame, text)
        local lbl = vgui.Create("DLabel", frame)
        lbl:SetPos(100, 10)
        lbl:SetSize(180, 80)
        lbl:SetText(text)
        lbl:SetTextColor(TEXT_COLOR)
        lbl:SetWrap(true)
        lbl:SetContentAlignment(5) -- Центрирование текста
    end

    -- Настройка фрейма уведомления
    local function SetupFrame(text, modelPath)
        local positions = GetNotificationPositions()
        local frame = vgui.Create("DPanel")
        frame:SetSize(NOTIFICATION_WIDTH, NOTIFICATION_HEIGHT)
        frame:SetPos(positions.startX, positions.y)
        frame:ParentToHUD()
        function frame:Paint(w, h)
            draw.RoundedBox(8, 0, 0, w, h, NOTIFICATION_BG_COLOR)
        end

        SetupTextLabel(frame, text)
        SetupModelPanel(frame, modelPath)
        return frame
    end

    -- Таймер для скрытия уведомления
    local function StartHideTimer(frame)
        timer.Simple(DISPLAY_DURATION, function()
            if IsValid(frame) then
                local _, y = frame:GetPos() -- Получаем y координату
                frame:MoveTo(ScrW(), y, ANIMATION_DURATION, 0, 3, function()
                    RemoveFrame(frame)
                    isNotificationShowing = false
                    -- Проверяем очередь на наличие следующих уведомлений
                    if #notificationQueue > 0 then
                        local nextNotification = table.remove(notificationQueue, 1)
                        CreateNotification(nextNotification.text, nextNotification.modelPath)
                    end
                end)
            end
        end)
    end

    -- Анимация появления фрейма
    local function AnimateFrame(frame)
        local positions = GetNotificationPositions()
        frame:MoveTo(positions.endX, positions.y, ANIMATION_DURATION, 0, 3, function() StartHideTimer(frame) end)
    end

    -- Основная функция создания уведомления
    local function CreateNotification(text, modelPath)
        if isNotificationShowing then
            -- Если уведомление уже показывается, добавляем новое в очередь
            table.insert(notificationQueue, {
                text = text,
                modelPath = modelPath
            })
            return
        end

        isNotificationShowing = true
        local frame = SetupFrame(text, modelPath)
        AnimateFrame(frame)
    end

    -- Глобальная функция для создания уведомления, доступная в глобальной области
    -- Можно сделать его локальной, если уведомления будут создаваться только через сетевые сообщения
    _G.CreateNotification = CreateNotification
    -- Обработка сетевого сообщения для показа уведомления
    net.Receive("ShowNotification", function()
        local text = net.ReadString()
        local model = net.ReadString()
        CreateNotification(text, model)
    end)

    -- Консольная команда для тестирования уведомления на клиенте
    concommand.Add("show_notification_client", function() CreateNotification("Это тестовое уведомление.", "models/player/alyx.mdl") end)
end
```
Найди несоответствия и ошибки в коде, устрани их, проведи рефакторинг и профилирование кода. Удали из кода неиспользуемые или излишние операции, напиши полный код для серверной части и для клиентской. Реализуй чтобы уведомление плавно выплывало сбоку.