diff --git a/garrysmod/gamemodes/militaryrp/plugins/serverlogs/cl_plugin.lua b/garrysmod/gamemodes/militaryrp/plugins/serverlogs/cl_plugin.lua index 26fa68f..2823f3b 100644 --- a/garrysmod/gamemodes/militaryrp/plugins/serverlogs/cl_plugin.lua +++ b/garrysmod/gamemodes/militaryrp/plugins/serverlogs/cl_plugin.lua @@ -311,22 +311,26 @@ function PLUGIN:UpdateLogsList() end for _, log in ipairs(clientLogs) do - local logEntry = vgui.Create("DPanel", self.logsList) - logEntry:SetTall(60) + local logEntry = vgui.Create("DButton", self.logsList) + logEntry:SetTall(66) logEntry:Dock(TOP) logEntry:DockMargin(5, 5, 5, 0) + logEntry:SetText("") local category = self.LOG_CATEGORIES[log.category] local categoryColor = category and category.color or color_white logEntry.Paint = function(s, w, h) - draw.RoundedBox(4, 0, 0, w, h, COLOR_BG_LIGHT) + local isHovered = s:IsHovered() or s:IsChildHovered() + local bgCol = isHovered and Color(18, 25, 20) or COLOR_BG_LIGHT + + draw.RoundedBox(4, 0, 0, w, h, bgCol) -- Боковая полоска категории draw.RoundedBoxEx(4, 0, 0, 5, h, categoryColor, true, false, true, false) -- Рамка - surface.SetDrawColor(COLOR_BORDER) + surface.SetDrawColor(isHovered and COLOR_PRIMARY or COLOR_BORDER) surface.DrawOutlinedRect(0, 0, w, h, 1) -- Время @@ -340,44 +344,58 @@ function PLUGIN:UpdateLogsList() draw.SimpleText(log.message, "ixSmallFont", 15, 43, COLOR_TEXT_PRIMARY, TEXT_ALIGN_LEFT, TEXT_ALIGN_TOP) end - -- Контекстное меню - logEntry.OnMousePressed = function(s, btn) - if btn == MOUSE_RIGHT then - local menu = DermaMenu() - - menu:AddOption("Копировать сообщение", function() - SetClipboardText(log.message) - ix.util.Notify("Сообщение скопировано") - end):SetIcon("icon16/page_copy.png") - - if log.target and log.target.steamid and log.target.steamid ~= "N/A" then - menu:AddOption("Копировать SteamID (" .. log.target.name .. ")", function() - SetClipboardText(log.target.steamid) - ix.util.Notify("SteamID скопирован: " .. log.target.steamid) - end):SetIcon("icon16/user_edit.png") - end - - if log.data and log.data.attacker and log.data.attacker ~= "world" then - menu:AddOption("Копировать SteamID Атакующего", function() - SetClipboardText(log.data.attacker) - ix.util.Notify("SteamID атакующего скопирован: " .. log.data.attacker) - end):SetIcon("icon16/user_delete.png") - end - - menu:AddSpacer() - - menu:AddOption("Копировать время (" .. log.timeString .. ")", function() - SetClipboardText(log.timeString) - end):SetIcon("icon16/time.png") - - menu:AddOption("Копировать полную строку", function() - local fullLog = string.format("[%s][%s] %s", log.timeString, category and category.name or log.category, log.message) - SetClipboardText(fullLog) - ix.util.Notify("Полная строка скопирована") - end):SetIcon("icon16/page_white_copy.png") - - menu:Open() + -- Поиск SteamID в тексте сообщения + local function findSteamID(text) + if not text then return nil end + return string.match(text, "STEAM_[0-5]:[0-9]:[0-9]+") + end + + local extractedID = findSteamID(log.message) + + logEntry.DoRightClick = function(s) + local menu = DermaMenu() + + -- Опция копирования основного сообщения + menu:AddOption("Копировать сообщение", function() + SetClipboardText(log.message) + ix.util.Notify("Сообщение скопировано") + end):SetIcon("icon16/page_copy.png") + + -- Копирование SteamID цели (если есть в метаданных) + if log.target and log.target.steamid and log.target.steamid ~= "N/A" then + menu:AddOption("Копировать SteamID (" .. log.target.name .. ")", function() + SetClipboardText(log.target.steamid) + ix.util.Notify("SteamID скопирован: " .. log.target.steamid) + end):SetIcon("icon16/user_edit.png") + -- Если нет в метаданных, но нашли в тексте (для архива) + elseif extractedID then + menu:AddOption("Копировать найденный SteamID (" .. extractedID .. ")", function() + SetClipboardText(extractedID) + ix.util.Notify("SteamID скопирован: " .. extractedID) + end):SetIcon("icon16/user_magnify.png") end + + -- Копирование SteamID атакующего (для убийств) + if log.data and log.data.attacker and log.data.attacker ~= "world" then + menu:AddOption("Копировать SteamID Атакующего", function() + SetClipboardText(log.data.attacker) + ix.util.Notify("SteamID атакующего скопирован: " .. log.data.attacker) + end):SetIcon("icon16/user_delete.png") + end + + menu:AddSpacer() + + menu:AddOption("Копировать время (" .. log.timeString .. ")", function() + SetClipboardText(log.timeString) + end):SetIcon("icon16/time.png") + + menu:AddOption("Копировать полную строку", function() + local fullLog = string.format("[%s][%s] %s", log.timeString, category and category.name or log.category, log.message) + SetClipboardText(fullLog) + ix.util.Notify("Полная строка скопирована") + end):SetIcon("icon16/page_white_copy.png") + + menu:Open() end end end diff --git a/garrysmod/gamemodes/militaryrp/plugins/serverlogs/sv_plugin.lua b/garrysmod/gamemodes/militaryrp/plugins/serverlogs/sv_plugin.lua index 35b03a9..9a20730 100644 --- a/garrysmod/gamemodes/militaryrp/plugins/serverlogs/sv_plugin.lua +++ b/garrysmod/gamemodes/militaryrp/plugins/serverlogs/sv_plugin.lua @@ -58,9 +58,14 @@ function PLUGIN:LoadPersistentLogs() local line = lines[i] if not line or line == "" or string.StartWith(line, "===") then continue end - -- Пример лога: [10:38:40][Боевые действия] Игрок умер - -- Нам нужно распарсить это обратно в таблицу - local timeStr, categoryName, msg = string.match(line, "%[(%d%d:%d%d:%d%d)%]%[(.-)%] (.*)") + -- Пробуем новый формат: [Время][Категория][SteamID] Сообщение + local timeStr, categoryName, steamid, msg = string.match(line, "^%[(%d%d:%d%d:%d%d)%]%[(.-)%]%[(STEAM_%d:%d:%d+)%] (.*)") + + -- Если не вышло, пробуем старый формат: [Время][Категория] Сообщение + if not timeStr then + timeStr, categoryName, msg = string.match(line, "^%[(%d%d:%d%d:%d%d)%]%[(.-)%] (.*)") + steamid = "N/A" + end if timeStr and categoryName and msg then -- Находим ID категории по имени @@ -74,10 +79,14 @@ function PLUGIN:LoadPersistentLogs() table.insert(logsToLoad, { id = #logsToLoad + 1, - type = "LOADED", -- Специальный тип для загруженных + type = "LOADED", category = categoryID, message = "[АРХИВ] " .. msg, - timestamp = 0, -- Мы не знаем точную дату, только время + target = { + name = steamid ~= "N/A" and steamid or "Архив", + steamid = steamid + }, + timestamp = 0, timeString = timeStr, isPersistent = true }) @@ -106,8 +115,8 @@ function PLUGIN:AddLog(logType, message, target, data) category = self.LOG_TYPES[logType].category, message = message, target = target and { - name = IsValid(target) and target:Nick() or tostring(target), - steamid = IsValid(target) and target:SteamID() or "N/A" + name = IsValid(target) and target:Nick() or (isstring(target) and target or tostring(target)), + steamid = IsValid(target) and target:SteamID() or (isstring(target) and string.match(target, "STEAM_%d:%d:%d+") and target or "N/A") } or nil, data = data or {}, timestamp = os.time(), @@ -124,9 +133,11 @@ function PLUGIN:AddLog(logType, message, target, data) -- Сохраняем в файл if self.logFile then - local logString = string.format("[%s][%s] %s\n", + local targetSID = (logEntry.target and logEntry.target.steamid ~= "N/A") and ("[" .. logEntry.target.steamid .. "]") or "" + local logString = string.format("[%s][%s]%s %s\n", logEntry.timeString, self.LOG_CATEGORIES[logEntry.category].name, + targetSID, message ) file.Append(self.logFile, logString)