This commit is contained in:
2026-03-31 10:59:30 +03:00
parent 0301242716
commit f457aa2a11
4 changed files with 180 additions and 9 deletions

View File

@@ -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

View File

@@ -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 = "Начало захвата точки"},

View File

@@ -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
-- ======================
-- ХУКИ ДЛЯ ЛОГИРОВАНИЯ
-- ======================