[chat] Почему-то не появляется текст, вводимый в окно ввода

Так вот, у меня на данный момент несколько проблем с чатом:
Не меняется префикс при выборе его на кнопках под чатом,
Не проигрывается действие, если выбрано /do или /me,
Как указано в названии не видно то, что ты вводишь в чат.

Ниже весь код…

Основа
AquaChat = AquaChat or {
    Prefixes = {
        ["OOC"] = { text = "OOC", color = Color(255, 255, 255) },
        ["Д"] = { text = "Д", color = Color(255, 105, 180) },
        ["Р"] = { text = "Р", color = Color(50, 255, 50) },
        ["Т"] = { text = "Т", color = Color(255, 165, 0) },
        ["М"] = { text = "М", color = Color(255, 50, 50) },
        ["В"] = { text = "В", color = Color(255, 50, 255) },
        ["R"] = { text = "RADIO", color = Color(100, 100, 255) },
        ["SERVER"] = { text = "СЕРВЕР", color = Color(255, 215, 0) },
        ["TEAM"] = { text = "TEAM", color = Color(100, 255, 100) },
        ["ADMIN"] = { text = "ADMIN", color = Color(255, 0, 0) },
        ["NOTIFY"] = { text = "", color = Color(255, 255, 255) },
        ["LOCAL"] = { text = "", color = Color(255, 255, 255) }
    },
    Background = Color(0, 0, 0, 180),
    TextColor = Color(255, 255, 255),
    MaxMessages = 100,
    FadeInTime = 0.3,
    FadeOutTime = 3,
    StayTime = 8,
    Font = "ChatFont",
    Width = ScrW() * 0.4, 
    LineHeight = 18,
    Messages = {},
    IsOpen = false,
    InputText = "",
    ChatEntry = nil,
    ScrollOffset = 0,
    VisibleMessages = 50, 
    WheelScrollSpeed = 3,
    ChatHistory = {},
    HistoryIndex = 0,
    ShowTimestamps = false,
    ShowBackground = true,
    DefaultChatType = "LOCAL",
    ChatButtons = {},
    ButtonColor = Color(70, 130, 180),
    ButtonPadding = 10,
    ButtonMargin = 5
}

surface.CreateFont("AquaChatFont", {
    font = "Montserrat",
    size = 16,
    weight = 500,
    antialias = true
})

-- Include other client-side components
include("aqua_chat_events.lua")
include("aqua_chat_gui.lua")
include("aqua_chat_draw.lua")
Отрисовка чата
hook.Add("HUDPaint", "AquaChat_DrawChat", function()

    AquaChat.X = AquaChat.X or (ScrW() - (AquaChat.Width or ScrW() * 0.4)) / 2
    AquaChat.Width = AquaChat.Width or ScrW() * 0.4
    AquaChat.LineHeight = AquaChat.LineHeight or 18
    local roundedCorners = 4

    surface.SetFont(AquaChat.Font)
    
    local messagesY = ScrH() * 0.7 - 10
    if IsValid(AquaChat.ChatEntry) then
        messagesY = AquaChat.ChatEntry:GetY() - 10
    end

    local maxMessagesToShow = AquaChat.IsOpen and (AquaChat.VisibleMessages or 50) or math.min(AquaChat.VisibleMessages or 50, 15)
    local startIndex = math.max(1, #AquaChat.Messages - maxMessagesToShow - (AquaChat.ScrollOffset or 0) + 1)
    local endIndex = math.min(#AquaChat.Messages, startIndex + maxMessagesToShow - 1)
    

    if AquaChat.IsOpen and input.IsMouseDown(MOUSE_LEFT) then
        local x, y = gui.MousePos()
        if x >= AquaChat.X and x <= AquaChat.X + AquaChat.Width then
            if y >= messagesY - maxMessagesToShow * AquaChat.LineHeight and y <= messagesY then
                AquaChat.ScrollOffset = math.Clamp((AquaChat.ScrollOffset or 0) + input.GetMouseWheel() * (AquaChat.WheelScrollSpeed or 3), 
                    0, math.max(0, #AquaChat.Messages - maxMessagesToShow))
            end
        end
    end

    for i = endIndex, startIndex, -1 do
        local msg = AquaChat.Messages[i]
        if not msg or not msg.visible then continue end
        
        local timeAlive = CurTime() - (msg.time or CurTime())
        local alpha = msg.alpha or 255

        if not AquaChat.IsOpen then
            if msg.fadingOut then
                local fadeProgress = (CurTime() - (msg.fadeStartTime or CurTime())) / (AquaChat.FadeOutTime or 3)
                alpha = 255 * (1 - fadeProgress)
                if fadeProgress >= 1 then
                    msg.visible = false
                    continue
                end
            elseif timeAlive < (AquaChat.FadeInTime or 0.3) then
                alpha = 255 * (timeAlive / (AquaChat.FadeInTime or 0.3))
            elseif timeAlive > (AquaChat.StayTime or 8) then
                alpha = 255 - (255 * ((timeAlive - (AquaChat.StayTime or 8)) / (AquaChat.FadeOutTime or 3)))
                if alpha <= 0 then
                    msg.visible = false
                    continue
                end
            else
                alpha = 255
            end
        end

        msg.alpha = alpha

        if alpha > 0 then
            local prefixData = AquaChat.Prefixes[msg.prefix] or AquaChat.Prefixes["OOC"] or {}
            local nickColor = IsValid(msg.ply) and msg.ply:IsPlayer() and team.GetColor(msg.ply:Team()) or Color(255, 255, 255, alpha)
            local textColor = Color(
                (AquaChat.TextColor or Color(255, 255, 255)).r,
                (AquaChat.TextColor or Color(255, 255, 255)).g,
                (AquaChat.TextColor or Color(255, 255, 255)).b,
                alpha
            )
            
            if msg.isDead then
                nickColor = Color(150, 150, 150, alpha)
            end

            local nick = IsValid(msg.ply) and msg.ply:IsPlayer() and msg.ply:Nick() or "Сервер"
            local mskTime = os.date("!%H:%M:%S", (msg.time or CurTime()) + 3 * 3600)
            local timestamp = (AquaChat.ShowTimestamps or false) and ("[" .. mskTime .. "] ") or ""
            local prefixText = (prefixData.text or "") ~= "" and ((prefixData.text or "") .. " ") or ""
            local nickText = msg.prefix ~= "NOTIFY" and (nick .. ": ") or ""

            if AquaChat.ShowBackground then
                draw.RoundedBox(roundedCorners, AquaChat.X, messagesY - (msg.height or AquaChat.LineHeight) - 2, 
                    AquaChat.Width, (msg.height or AquaChat.LineHeight) + 4, 
                    Color(
                        (AquaChat.Background or Color(0, 0, 0, 180)).r,
                        (AquaChat.Background or Color(0, 0, 0, 180)).g,
                        (AquaChat.Background or Color(0, 0, 0, 180)).b,
                        alpha * 0.7
                    )
                )
            end
            
            local textY = messagesY - (msg.height or AquaChat.LineHeight)
            
            if msg.prefix == "NOTIFY" then
                draw.SimpleText(msg.text or "", AquaChat.Font, AquaChat.X + 5, textY, textColor)
            else
                local xPos = AquaChat.X + 5
                
                if AquaChat.ShowTimestamps then
                    local timeW = surface.GetTextSize(timestamp) + 10
                    draw.RoundedBox(roundedCorners, xPos, textY, timeW, AquaChat.LineHeight, Color(50, 50, 50, alpha * 0.7))
                    draw.SimpleText(timestamp, AquaChat.Font, xPos + 5, textY, Color(200, 200, 200, alpha))
                    xPos = xPos + timeW + 5
                end
                
                if (prefixData.text or "") ~= "" then
                    local prefixW = surface.GetTextSize(prefixData.text) + 10
                    draw.RoundedBox(roundedCorners, xPos, textY, prefixW, AquaChat.LineHeight, 
                        Color(
                            (prefixData.color or Color(255, 255, 255)).r,
                            (prefixData.color or Color(255, 255, 255)).g,
                            (prefixData.color or Color(255, 255, 255)).b,
                            alpha * 0.7
                        )
                    )
                    draw.SimpleText(prefixData.text, AquaChat.Font, xPos + 5, textY, Color(255, 255, 255, alpha))
                    xPos = xPos + prefixW + 5
                end
                
                draw.SimpleText(nick .. (IsValid(msg.ply) and msg.ply:IsPlayer() and ":" or ""), AquaChat.Font, xPos, textY, nickColor)
                xPos = xPos + surface.GetTextSize(nick .. (IsValid(msg.ply) and msg.ply:IsPlayer() and ": " or " "))
                
                if msg.lines and #msg.lines > 0 then
                    for j, line in ipairs(msg.lines) do
                        if j > 1 then
                            textY = textY + AquaChat.LineHeight + 2
                        end
                        draw.SimpleText(line, AquaChat.Font, xPos, textY, textColor)
                    end
                end
            end
            
            messagesY = messagesY - (msg.height or AquaChat.LineHeight) - 8
        end
    end
    
    if AquaChat.IsOpen and IsValid(AquaChat.ChatEntry) then
        AquaChat.ChatEntry:PaintManual()
    end
end)
Ивенты
local function AddMessage(prefix, ply, text, isDead)
    local msg = {
        prefix = prefix,
        ply = IsValid(ply) and ply or Entity(0),
        text = text,
        time = CurTime(),
        alpha = AquaChat.IsOpen and 255 or 0,
        width = 0,
        height = AquaChat.LineHeight,
        isDead = isDead or false,
        visible = true,
        lines = {},
        fadingOut = false
    }

    surface.SetFont(AquaChat.Font)
    local maxWidth = AquaChat.Width - 20
    local words = string.Explode(" ", text)
    local currentLine = ""
    
    for _, word in ipairs(words) do
        local testLine = currentLine == "" and word or currentLine .. " " .. word
        local lineWidth = surface.GetTextSize(testLine)
        
        if lineWidth <= maxWidth then
            currentLine = testLine
        else
            if currentLine ~= "" then
                table.insert(msg.lines, currentLine)
            end
            currentLine = word
        end
    end
    
    if currentLine ~= "" then
        table.insert(msg.lines, currentLine)
    end
    
    if #msg.lines > 1 then
        msg.height = AquaChat.LineHeight * #msg.lines + (#msg.lines - 1) * 2
    end

    table.insert(AquaChat.Messages, msg)

    if #AquaChat.Messages > AquaChat.MaxMessages then
        table.remove(AquaChat.Messages, 1)
    end
end

net.Receive("AquaChat_AddMessage", function()
    local prefix = net.ReadString()
    local ply = net.ReadEntity()
    local text = net.ReadString()
    AddMessage(prefix, ply, text)
end)

hook.Add("OnPlayerChat", "AquaChat_HandleAllMessages", function(ply, text, isTeam, isDead)
    local prefix = isTeam and "TEAM" or "OOC"
    if ply == LocalPlayer() then
        prefix = isTeam and "TEAM" or AquaChat.DefaultChatType
    elseif not IsValid(ply) then
        prefix = "SERVER"
    end
    AddMessage(prefix, ply, text, isDead)
end)

hook.Add("ChatText", "AquaChat_ServerMessages", function(index, name, text, type)
    local prefixType = (type == "joinleave" or type == "none") and "NOTIFY" or "SERVER"
    AddMessage(prefixType, Entity(0), text)
end)

hook.Add("OnChatTab", "AquaChat_SAMMessages", function(text)
    AddMessage("ADMIN", Entity(0), text)
end)

hook.Add("Initialize", "AquaChat_OverrideChat", function()
    function GAMEMODE:StartChat()
        AquaChat.OpenChat()
        return true
    end

    function GAMEMODE:FinishChat()
        AquaChat.CloseChat()
    end
end)
GUI
function AquaChat.OpenChat()
    if AquaChat.IsOpen then return end
    
    AquaChat.IsOpen = true
    
    for _, msg in ipairs(AquaChat.Messages) do
        msg.alpha = 255
        msg.visible = true
        msg.fadingOut = false
    end
    
    if IsValid(AquaChat.ChatEntry) then
        AquaChat.ChatEntry:Remove()
    end
    

    AquaChat.X = (ScrW() - AquaChat.Width) / 2
    local inputY = ScrH() * 0.7 
    
    AquaChat.ChatEntry = vgui.Create("DTextEntry")
    AquaChat.ChatEntry:SetSize(AquaChat.Width, 25)
    AquaChat.ChatEntry:SetPos(AquaChat.X, inputY)
    AquaChat.ChatEntry:SetText("")
    AquaChat.ChatEntry:SetTextColor(Color(255, 255, 255))
    AquaChat.ChatEntry:SetFont("AquaChatFont")
    AquaChat.ChatEntry:SetDrawLanguageID(false)
    AquaChat.ChatEntry:RequestFocus()
    AquaChat.ChatEntry:SetHistoryEnabled(true)
    
    AquaChat.ChatEntry.Paint = function(self, w, h)
        draw.RoundedBox(4, 0, 0, w, h, Color(0, 0, 0, 200))
        self:DrawTextEntryText(Color(255, 255, 255), Color(30, 130, 255), Color(255, 255, 255))
    end
    
    AquaChat.ChatEntry.OnEnter = function(self)
        local text = self:GetText()
        if text ~= "" then
            table.insert(AquaChat.ChatHistory, 1, text)
            
            if AquaChat.DefaultChatType ~= "LOCAL" and not string.StartWith(text, "/") then
                local cmd = ({
                    ["OOC"] = "/OOC ",
                    ["Д"] = "/ME ",
                    ["Р"] = "/DO ",
                    ["Т"] = "/Т ",
                    ["М"] = "/М ",
                    ["В"] = "/SHOUT ",
                })[AquaChat.DefaultChatType] or ""
                
                text = cmd .. text
            end
            
            LocalPlayer():ConCommand("say " .. text)
        end
        AquaChat.HistoryIndex = 0
        AquaChat.CloseChat()
    end
    
    AquaChat.ChatEntry.OnTextChanged = function(self)
        AquaChat.InputText = self:GetText()
    end
    
    AquaChat.ChatEntry.OnKeyCodeTyped = function(self, code)
        if code == KEY_UP then
            if AquaChat.HistoryIndex < #AquaChat.ChatHistory then
                AquaChat.HistoryIndex = AquaChat.HistoryIndex + 1
                self:SetText(AquaChat.ChatHistory[AquaChat.HistoryIndex])
                self:SetCaretPos(#self:GetText())
            end
        elseif code == KEY_DOWN then
            if AquaChat.HistoryIndex > 0 then
                AquaChat.HistoryIndex = AquaChat.HistoryIndex - 1
                if AquaChat.HistoryIndex == 0 then
                    self:SetText("")
                else
                    self:SetText(AquaChat.ChatHistory[AquaChat.HistoryIndex])
                end
                self:SetCaretPos(#self:GetText())
            end
        elseif code == KEY_TAB then

            local types = {"LOCAL", "OOC", "Д", "Р", "Т", "М", "В"}
            local currentIndex = table.KeyFromValue(types, AquaChat.DefaultChatType) or 1
            AquaChat.DefaultChatType = types[(currentIndex % #types) + 1]
            
            local currentText = self:GetText()
            if not string.StartWith(currentText, "/") then
                local cmd = ({
                    ["OOC"] = "/ooc ",
                    ["Д"] = "/me ",
                    ["Р"] = "/do ",
                    ["Т"] = "/t ",
                    ["М"] = "/m ",
                    ["В"] = "/shout ",
                    ["LOCAL"] = ""
                })[AquaChat.DefaultChatType] or ""
                
                self:SetText(cmd .. currentText)
                self:SetCaretPos(string.len(cmd .. currentText))
            end
            return true
        end
    end
    
    AquaChat.CreateButtons()
end

function AquaChat.CreateButtons()
    for _, btn in pairs(AquaChat.ChatButtons) do
        if IsValid(btn) then
            btn:Remove()
        end
    end
    AquaChat.ChatButtons = {}

    local buttonTypes = {
        {type = "LOCAL", text = "Локальный", command = ""},
        {type = "OOC", text = "OOC", command = "/ooc "},
        {type = "Д", text = "Действие", command = "/me "},
        {type = "Р", text = "Роль", command = "/do "},
        {type = "Т", text = "Тихо", command = "/t "},
        {type = "М", text = "МЕГАФОН", command = "/m "},
        {type = "В", text = "Крик", command = "/shout "}
    }

    local buttonY = (AquaChat.ChatEntry and AquaChat.ChatEntry:GetY() or ScrH() * 0.7) + 30
    local currentX = AquaChat.X

    surface.SetFont("AquaChatFont")
    
    for _, btnData in ipairs(buttonTypes) do
        local textWidth = surface.GetTextSize(btnData.text)
        local btnWidth = textWidth + AquaChat.ButtonPadding * 2
        
        local btn = vgui.Create("DButton")
        btn:SetSize(btnWidth, 25)
        btn:SetPos(currentX, buttonY)
        btn:SetText(btnData.text)
        btn:SetTextColor(Color(255, 255, 255))
        btn:SetFont("AquaChatFont")
        
        btn.Paint = function(self, w, h)
            local bgColor = Color(AquaChat.ButtonColor.r, AquaChat.ButtonColor.g, AquaChat.ButtonColor.b, 
                AquaChat.DefaultChatType == btnData.type and 200 or 100)
            draw.RoundedBox(4, 0, 0, w, h, bgColor)
        end
        
        btn.DoClick = function()
            AquaChat.DefaultChatType = btnData.type
            if IsValid(AquaChat.ChatEntry) then
                local currentText = AquaChat.ChatEntry:GetText()
                if currentText == "" or not string.StartWith(currentText, "/") then
                    AquaChat.ChatEntry:SetText(btnData.command)
                    AquaChat.ChatEntry:SetCaretPos(string.len(btnData.command))
                end
            end
        end
        
        table.insert(AquaChat.ChatButtons, btn)
        currentX = currentX + btnWidth + AquaChat.ButtonMargin
    end
end

function AquaChat.CloseChat()
    if not AquaChat.IsOpen then return end
    
    AquaChat.IsOpen = false
    local closeTime = CurTime()
    
    for _, msg in ipairs(AquaChat.Messages) do
        msg.fadingOut = true
        msg.fadeStartTime = closeTime
    end
    
    if IsValid(AquaChat.ChatEntry) then
        AquaChat.ChatEntry:Remove()
        AquaChat.ChatEntry = nil
    end
    
    for _, btn in pairs(AquaChat.ChatButtons) do
        if IsValid(btn) then
            btn:Remove()
        end
    end
    AquaChat.ChatButtons = {}
    
    gui.HideGameUI()
end

hook.Add("PlayerBindPress", "AquaChat_MouseWheelScroll", function(ply, bind, pressed)
    if not AquaChat.IsOpen then return end
    
    if bind == "invnext" then
        AquaChat.ScrollOffset = math.min(AquaChat.ScrollOffset + AquaChat.WheelScrollSpeed, 
            math.max(0, #AquaChat.Messages - AquaChat.VisibleMessages))
        return true
    elseif bind == "invprev" then
        AquaChat.ScrollOffset = math.max(AquaChat.ScrollOffset - AquaChat.WheelScrollSpeed, 0)
        return true
    end
end)

hook.Add("GUIMousePressed", "AquaChat_CloseOnClick", function()
    if AquaChat.IsOpen then
        AquaChat.CloseChat()
    end
end)

concommand.Add("aquachat_toggle_timestamps", function()
    AquaChat.ShowTimestamps = not AquaChat.ShowTimestamps
    print("Timestamps are now " .. (AquaChat.ShowTimestamps and "enabled" or "disabled"))
end)

concommand.Add("aquachat_toggle_background", function()
    AquaChat.ShowBackground = not AquaChat.ShowBackground
    print("Chat background is now " .. (AquaChat.ShowBackground and "enabled" or "disabled"))
end)
SV часть
if SERVER then
    util.AddNetworkString("AquaChat_AddMessage")

    hook.Add("PlayerSay", "AquaChat_HandleChat", function(ply, text, isTeam)
        if string.StartWith(text, "/") then
            local spacePos = string.find(text, " ") or (#text + 1)
            local cmd = string.sub(text, 2, spacePos - 1):upper()
            local msg = string.sub(text, spacePos + 1)

            local prefix = ({
                ["OOC"] = "OOC",
                ["Д"] = "Д",
                ["Р"] = "Р",
                ["Т"] = "Т",
                ["М"] = "М",
                ["В"] = "В",
                ["R"] = "R",
                ["ME"] = "Д",
                ["DO"] = "Р",
                ["SHOUT"] = "В",
                ["К"] = "В",
                ["LOCAL"] = "LOCAL"
            })[cmd]

            if prefix then
                if cmd == "ME" then
                    msg = "* " .. ply:Nick() .. " " .. msg
                elseif cmd == "DO" then
                    msg = "* " .. msg .. " (" .. ply:Nick() .. ")"
                end

                net.Start("AquaChat_AddMessage")
                    net.WriteString(prefix)
                    net.WriteEntity(ply)
                    net.WriteString(msg)
                net.Broadcast()
                return ""
            end
        else
            net.Start("AquaChat_AddMessage")
                net.WriteString("LOCAL")
                net.WriteEntity(ply)
                net.WriteString(text)
            net.Broadcast()
            return ""
        end
    end)
end