From f457aa2a11db04d02f499e10432372f4030606f3 Mon Sep 17 00:00:00 2001 From: Scripty Date: Tue, 31 Mar 2026 10:59:30 +0300 Subject: [PATCH] 1 --- .../plugins/serverlogs/cl_plugin.lua | 40 ++++++ .../plugins/serverlogs/sh_plugin.lua | 4 + .../plugins/serverlogs/sv_plugin.lua | 125 ++++++++++++++++-- .../plugins/whitelistmenu/sv_plugin.lua | 20 +++ 4 files changed, 180 insertions(+), 9 deletions(-) diff --git a/garrysmod/gamemodes/militaryrp/plugins/serverlogs/cl_plugin.lua b/garrysmod/gamemodes/militaryrp/plugins/serverlogs/cl_plugin.lua index a9188b1..26fa68f 100644 --- a/garrysmod/gamemodes/militaryrp/plugins/serverlogs/cl_plugin.lua +++ b/garrysmod/gamemodes/militaryrp/plugins/serverlogs/cl_plugin.lua @@ -339,5 +339,45 @@ 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() + end + end end end diff --git a/garrysmod/gamemodes/militaryrp/plugins/serverlogs/sh_plugin.lua b/garrysmod/gamemodes/militaryrp/plugins/serverlogs/sh_plugin.lua index 86769f7..00fe7b6 100644 --- a/garrysmod/gamemodes/militaryrp/plugins/serverlogs/sh_plugin.lua +++ b/garrysmod/gamemodes/militaryrp/plugins/serverlogs/sh_plugin.lua @@ -99,6 +99,10 @@ PLUGIN.LOG_TYPES = { CHARACTER_CREATE = {category = "CHARACTER", description = "Создание персонажа"}, CHARACTER_DELETE = {category = "CHARACTER", description = "Удаление персонажа"}, CHARACTER_SWITCH = {category = "CHARACTER", description = "Смена персонажа"}, + CHARACTER_WHITELIST = {category = "CHARACTER", description = "Изменение вайтлиста/статистики"}, + + -- Команды + COMMAND_RUN = {category = "ADMIN", description = "Выполнена админ-команда"}, -- Захват точек CAPTURE_START = {category = "COMBAT", description = "Начало захвата точки"}, diff --git a/garrysmod/gamemodes/militaryrp/plugins/serverlogs/sv_plugin.lua b/garrysmod/gamemodes/militaryrp/plugins/serverlogs/sv_plugin.lua index 3d0f964..35b03a9 100644 --- a/garrysmod/gamemodes/militaryrp/plugins/serverlogs/sv_plugin.lua +++ b/garrysmod/gamemodes/militaryrp/plugins/serverlogs/sv_plugin.lua @@ -16,18 +16,81 @@ function PLUGIN:InitializeLogSystem() self.logFile = nil -- Создаем папку для логов + local logPath = ix.config.Get("logFilePath", "helix_logs") + if not file.Exists(logPath, "DATA") then + file.CreateDir(logPath) + end + if ix.config.Get("logSaveToFile", true) then - local logPath = ix.config.Get("logFilePath", "helix_logs") - if not file.Exists(logPath, "DATA") then - file.CreateDir(logPath) - end - -- Создаем файл для текущей сессии local date = os.date("%Y-%m-%d_%H-%M-%S") self.logFile = logPath .. "/log_" .. date .. ".txt" file.Write(self.logFile, "=== Server Logs Started: " .. os.date("%Y-%m-%d %H:%M:%S") .. " ===\n") end + + -- Загружаем логи из предыдущей сессии + self:LoadPersistentLogs() +end + +-- Загрузка логов из файлов +function PLUGIN:LoadPersistentLogs() + local logPath = ix.config.Get("logFilePath", "helix_logs") + local files, _ = file.Find(logPath .. "/log_*.txt", "DATA") + + if #files == 0 then return end + + -- Сортируем файлы по дате (в обратном порядке) + table.sort(files, function(a, b) return a > b end) + + local logsToLoad = {} + local maxToLoad = 500 -- Лимит загрузки для производительности + + for _, fileName in ipairs(files) do + if #logsToLoad >= maxToLoad then break end + + local content = file.Read(logPath .. "/" .. fileName, "DATA") + if not content then continue end + + local lines = string.Split(content, "\n") + -- Читаем с конца + for i = #lines, 1, -1 do + 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)%]%[(.-)%] (.*)") + + if timeStr and categoryName and msg then + -- Находим ID категории по имени + local categoryID = "ADMIN" + for catID, cat in pairs(self.LOG_CATEGORIES) do + if cat.name == categoryName then + categoryID = catID + break + end + end + + table.insert(logsToLoad, { + id = #logsToLoad + 1, + type = "LOADED", -- Специальный тип для загруженных + category = categoryID, + message = "[АРХИВ] " .. msg, + timestamp = 0, -- Мы не знаем точную дату, только время + timeString = timeStr, + isPersistent = true + }) + + if #logsToLoad >= maxToLoad then break end + end + end + end + + -- Переворачиваем чтобы были по хронологии и добавляем в начало текущих логов + for i = #logsToLoad, 1, -1 do + table.insert(self.logs, logsToLoad[i]) + end end -- Добавление лога @@ -154,14 +217,58 @@ net.Receive("ixServerLogs_Request", function(len, client) end end) --- Очистка логов -net.Receive("ixServerLogs_Clear", function(len, client) - if not client:IsSuperAdmin() then return end - PLUGIN.logs = {} PLUGIN:AddLog("ADMIN_COMMAND", client:Nick() .. " очистил логи сервера", client) end) +-- Выполнение админ-команд +function PLUGIN:OnCommandRun(client, command, arguments) + if not IsValid(client) then return end + + local cmdObj = ix.command.list[string.lower(command)] + if not cmdObj then return end + + -- Логируем только если команда админская или важная + if cmdObj.adminOnly or cmdObj.superAdminOnly or cmdObj.privilege then + local argsStr = table.concat(arguments, " ") + local message = string.format("%s выполнил команду: /%s %s", client:Nick(), command, argsStr) + + self:AddLog("COMMAND_RUN", message, client, { + command = command, + args = arguments + }) + end +end + +-- Самоубийство +function PLUGIN:CanPlayerSuicide(client) + self:AddLog("PLAYER_DEATH", client:Nick() .. " пытается совершить самоубийство", client) +end + +-- Поднятие предмета +function PLUGIN:PlayerPickupItem(client, item) + if not IsValid(client) or not item then return end + + local itemName = item.GetName and item:GetName() or item.name or "Предмет" + local message = string.format("%s поднял предмет: %s", client:Nick(), itemName) + + self:AddLog("ITEM_PICKUP", message, client, { + item = itemName + }) +end + +-- Выбрасывание предмета +function PLUGIN:PlayerDroppedItem(client, item) + if not IsValid(client) or not item then return end + + local itemName = item.GetName and item:GetName() or item.name or "Предмет" + local message = string.format("%s выбросил предмет: %s", client:Nick(), itemName) + + self:AddLog("ITEM_DROP", message, client, { + item = itemName + }) +end + -- ====================== -- ХУКИ ДЛЯ ЛОГИРОВАНИЯ -- ====================== diff --git a/garrysmod/gamemodes/militaryrp/plugins/whitelistmenu/sv_plugin.lua b/garrysmod/gamemodes/militaryrp/plugins/whitelistmenu/sv_plugin.lua index 815ad6c..12a8084 100644 --- a/garrysmod/gamemodes/militaryrp/plugins/whitelistmenu/sv_plugin.lua +++ b/garrysmod/gamemodes/militaryrp/plugins/whitelistmenu/sv_plugin.lua @@ -102,4 +102,24 @@ net.Receive("ixWhitelistMenuApply", function(_, client) client:Notify("Роль назначена: " .. target:Name()) target:Notify("Вам назначена новая роль!") + + -- Логирование в систему серверных логов + local serverlogs = ix.plugin.list["serverlogs"] + if serverlogs then + local factionName = faction.name or "Неизвестно" + local podrName = faction.Podr[podrID] and faction.Podr[podrID].name or tostring(podrID) + local specName = faction.Spec[specID] and faction.Spec[specID].name or tostring(specID) + local rankName = targetRanks[rankID] and targetRanks[rankID].name or tostring(rankID) + + local message = string.format("%s изменил роль игроку %s: Фракция: %s, Подразделение: %s, Спец: %s, Ранг: %s", + client:Nick(), target:Nick(), factionName, podrName, specName, rankName) + + serverlogs:AddLog("CHARACTER_WHITELIST", message, target, { + admin = client:SteamID(), + faction = factionName, + podr = podrName, + spec = specName, + rank = rankName + }) + end end)