mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
Upload
This commit is contained in:
265
lua/sam/menu/cl_init.lua
Normal file
265
lua/sam/menu/cl_init.lua
Normal file
@@ -0,0 +1,265 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
if SAM_LOADED then return end
|
||||
|
||||
local vgui = vgui
|
||||
local draw = draw
|
||||
|
||||
local sam = sam
|
||||
local sui = sui
|
||||
local TDLib = sui.TDLib
|
||||
|
||||
local config = sam.config
|
||||
|
||||
do
|
||||
local funcs = {
|
||||
["SAM.ComboBox"] = {
|
||||
event = "OnSelect",
|
||||
function(s, _, value)
|
||||
config.set(s.config_key, value)
|
||||
end
|
||||
},
|
||||
["SAM.TextEntry"] = {
|
||||
event = "OnEnter",
|
||||
function(s)
|
||||
local v = s:GetText()
|
||||
if s:GetNumeric() then
|
||||
v = tonumber(v)
|
||||
end
|
||||
config.set(s.config_key, v)
|
||||
end
|
||||
},
|
||||
["SAM.ToggleButton"] = {
|
||||
event = "OnChange",
|
||||
function(s, v)
|
||||
config.set(s.config_key, v)
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
sam.SUI = sam.SUI or sui.new("SAM", true, {
|
||||
SetConfig = function(s, key, default)
|
||||
s.config_key = key
|
||||
|
||||
local i = config.hook({key}, function(value, old)
|
||||
local v = config.get(key, default)
|
||||
s:SetValue(v)
|
||||
end)
|
||||
|
||||
local t = funcs[s:GetName()]
|
||||
s[t.event] = t[1]
|
||||
|
||||
s:On("OnRemove", function()
|
||||
config.remove_hook(i)
|
||||
end)
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
local SUI = sam.SUI
|
||||
local GetColor = SUI.GetColor
|
||||
|
||||
sam.menu = {}
|
||||
|
||||
local tabs = {}
|
||||
function sam.menu.add_tab(icon, func, check, pos)
|
||||
local tab = {
|
||||
icon = icon,
|
||||
func = func,
|
||||
check = check,
|
||||
pos = pos
|
||||
}
|
||||
for k, v in ipairs(tabs) do
|
||||
if v.icon == icon then
|
||||
tabs[k] = tab
|
||||
return
|
||||
end
|
||||
end
|
||||
table.insert(tabs, tab)
|
||||
end
|
||||
|
||||
function sam.menu.remove_tab(name)
|
||||
for k, v in ipairs(tabs) do
|
||||
if v.name == name then
|
||||
table.remove(tabs, k)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SAM_TAB_TITLE_FONT = SUI.CreateFont("TabTitle", "Roboto Bold", 22)
|
||||
SAM_TAB_DESC_FONT = SUI.CreateFont("TabDesc", "Roboto Medium", 15)
|
||||
|
||||
local MENU_LOADING = SUI.CreateFont("MenuLoading", "Roboto", 30)
|
||||
|
||||
SUI.AddToTheme("Dark", {
|
||||
frame = "#181818",
|
||||
|
||||
scroll_panel = "#181818",
|
||||
|
||||
menu_tabs_title = "#ffffff",
|
||||
|
||||
--=--
|
||||
player_list_titles = "#f2f1ef",
|
||||
|
||||
player_list_names = "#eeeeee",
|
||||
player_list_names_2 = "#ff6347",
|
||||
player_list_data = "#e8e8e8",
|
||||
|
||||
player_list_rank = "#41b9ff",
|
||||
player_list_console = "#00c853",
|
||||
player_list_rank_text = "#2c3e50",
|
||||
|
||||
player_list_steamid = "#a4a4a4",
|
||||
--=--
|
||||
|
||||
--=--
|
||||
actions_button = Color(0, 0, 0, 0),
|
||||
actions_button_hover = Color(200, 200, 200, 60),
|
||||
|
||||
actions_button_icon = "#aaaaaa",
|
||||
actions_button_icon_hover = "#ffffff",
|
||||
--=--
|
||||
|
||||
--=--
|
||||
page_switch_bg = "#222222",
|
||||
--=--
|
||||
})
|
||||
|
||||
SUI.SetTheme("Dark")
|
||||
|
||||
function SUI.panels.Frame:Paint(w, h)
|
||||
if GetColor("frame_blur") then
|
||||
TDLib.BlurPanel(self)
|
||||
end
|
||||
|
||||
draw.RoundedBox(8, 0, 0, w, h, GetColor("frame"))
|
||||
end
|
||||
|
||||
function SUI.panels.Frame:HeaderPaint(w, h)
|
||||
draw.RoundedBoxEx(8, 0, 0, w, h, GetColor("header"), true, true, false, false)
|
||||
draw.RoundedBox(0, 0, h - 1, w, 1, GetColor("line"))
|
||||
end
|
||||
|
||||
do
|
||||
function sam.menu.add_loading_panel(parent)
|
||||
local is_loading = false
|
||||
|
||||
local loading_panel = parent:Add("Panel")
|
||||
loading_panel:SetVisible(false)
|
||||
loading_panel:SetZPos(999999)
|
||||
loading_panel:SetMouseInputEnabled(false)
|
||||
|
||||
function loading_panel:Paint(w, h)
|
||||
draw.RoundedBox(3, 0, 0, w, h, Color(50, 50, 50, 200))
|
||||
draw.SimpleText(string.rep(".", (CurTime() * 3) % 3), MENU_LOADING, w/2, h/2, Color(200, 200, 200, 200), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
|
||||
end
|
||||
|
||||
parent:SUI_TDLib()
|
||||
parent:On("PerformLayout", function(s, w, h)
|
||||
loading_panel:SetSize(w, h)
|
||||
end)
|
||||
|
||||
local first = true
|
||||
local toggle_loading = function(bool)
|
||||
if not IsValid(loading_panel) then return end
|
||||
|
||||
is_loading = bool or not is_loading
|
||||
if is_loading and not first then
|
||||
loading_panel:SetVisible(is_loading and true or false)
|
||||
loading_panel:SetMouseInputEnabled(is_loading)
|
||||
else
|
||||
timer.Simple(0.2, function()
|
||||
if not IsValid(loading_panel) then return end
|
||||
loading_panel:SetVisible(is_loading and true or false)
|
||||
loading_panel:SetMouseInputEnabled(is_loading)
|
||||
end)
|
||||
end
|
||||
|
||||
first = false
|
||||
end
|
||||
|
||||
return toggle_loading, function()
|
||||
return is_loading
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local sam_menu
|
||||
function sam.menu.open_menu()
|
||||
if IsValid(sam_menu) then
|
||||
return sam_menu:IsVisible() and sam_menu:Hide() or sam_menu:Show()
|
||||
-- sam_menu:Remove()
|
||||
end
|
||||
|
||||
sam_menu = vgui.Create("SAM.Frame")
|
||||
sam_menu:Center()
|
||||
sam_menu:MakePopup()
|
||||
sam_menu:SetTitle("SAM")
|
||||
|
||||
sam_menu:AddAnimations(800, 600)
|
||||
|
||||
sam_menu.close.DoClick = function()
|
||||
sam_menu:Hide()
|
||||
end
|
||||
|
||||
local sheet = sam_menu:Add("SAM.ColumnSheet")
|
||||
sheet:Dock(FILL)
|
||||
sheet:InvalidateParent(true)
|
||||
sheet:InvalidateLayout(true)
|
||||
sheet.Paint = nil
|
||||
|
||||
local tab_scroller = sheet.tab_scroller
|
||||
tab_scroller:DockMargin(0, 1, 0, 1)
|
||||
|
||||
function tab_scroller:Paint(w, h)
|
||||
draw.RoundedBoxEx(8, 0, 0, w, h, GetColor("column_sheet_bar"), false, false, true, false)
|
||||
end
|
||||
|
||||
local sheets = {}
|
||||
for _, v in SortedPairsByMemberValue(tabs, "pos") do
|
||||
sheets[v.icon] = sheet:AddSheet(v.icon, v.func)
|
||||
end
|
||||
|
||||
tab_scroller = tab_scroller:GetCanvas()
|
||||
sam_menu:On("Think", function()
|
||||
for _, v in ipairs(tabs) do
|
||||
local tab = sheets[v.icon]
|
||||
if v.check and not v.check() then
|
||||
if tab:IsVisible() then
|
||||
tab:SetVisible(false)
|
||||
if sheet:GetActiveTab() == tab then
|
||||
sheet:SetActiveTab(sheet.tabs[1])
|
||||
end
|
||||
tab_scroller:InvalidateLayout()
|
||||
end
|
||||
elseif not tab:IsVisible() then
|
||||
tab:SetVisible(true)
|
||||
tab_scroller:InvalidateLayout()
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function sam.menu.get()
|
||||
return sam_menu
|
||||
end
|
||||
|
||||
hook.Add("GUIMouseReleased", "SAM.CloseMenu", function(mouse_code)
|
||||
local panel = vgui.GetHoveredPanel()
|
||||
if mouse_code == MOUSE_LEFT and panel == vgui.GetWorldPanel() and IsValid(sam_menu) and sam_menu:HasHierarchicalFocus() then
|
||||
sam_menu:Hide()
|
||||
end
|
||||
end)
|
||||
|
||||
for _, f in ipairs(file.Find("sam/menu/tabs/*.lua", "LUA")) do
|
||||
sam.load_file("sam/menu/tabs/" .. f, "sh")
|
||||
end
|
||||
34
lua/sam/menu/sh_init.lua
Normal file
34
lua/sam/menu/sh_init.lua
Normal file
@@ -0,0 +1,34 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
if SAM_LOADED then return end
|
||||
|
||||
require("sui")
|
||||
|
||||
sam.command.new("menu")
|
||||
:Help("Open admin mod menu")
|
||||
:MenuHide()
|
||||
:DisableNotify()
|
||||
:OnExecute(function(ply)
|
||||
sam.netstream.Start(ply, "OpenMenu")
|
||||
end)
|
||||
:End()
|
||||
|
||||
if CLIENT then
|
||||
sam.netstream.Hook("OpenMenu", function()
|
||||
sam.menu.open_menu()
|
||||
end)
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
for _, f in ipairs(file.Find("sam/menu/tabs/*.lua", "LUA")) do
|
||||
sam.load_file("sam/menu/tabs/" .. f)
|
||||
end
|
||||
end
|
||||
419
lua/sam/menu/tabs/bans.lua
Normal file
419
lua/sam/menu/tabs/bans.lua
Normal file
@@ -0,0 +1,419 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
if SAM_LOADED then return end
|
||||
|
||||
local sam = sam
|
||||
local SQL = sam.SQL
|
||||
local SUI = sam.SUI
|
||||
local netstream = sam.netstream
|
||||
|
||||
sam.permissions.add("manage_bans", nil, "superadmin")
|
||||
|
||||
local get_pages_count = function(bans_count)
|
||||
bans_count = bans_count / 35
|
||||
local i2 = math.floor(bans_count)
|
||||
return bans_count ~= i2 and i2 + 1 or bans_count
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
local check = function(ply)
|
||||
return ply:HasPermission("manage_bans") and ply:sam_check_cooldown("MenuManageBans", 0.1)
|
||||
end
|
||||
|
||||
local limit = 35
|
||||
|
||||
local get_page_count = function(res, callback, page, order_by, keyword)
|
||||
local current_time = os.time()
|
||||
local query = [[
|
||||
SELECT
|
||||
COUNT(`steamid`) AS `count`
|
||||
FROM
|
||||
`sam_bans`
|
||||
WHERE
|
||||
(`unban_date` >= %d OR `unban_date` = 0)]]
|
||||
|
||||
query = query:format(current_time)
|
||||
|
||||
if keyword then
|
||||
query = query .. " AND `steamid` LIKE " .. SQL.Escape("%" .. keyword .. "%")
|
||||
end
|
||||
|
||||
SQL.Query(query, callback, true, {res, page, order_by, keyword, current_time})
|
||||
end
|
||||
|
||||
local resolve_promise = function(data, arguments)
|
||||
local res = arguments[1]
|
||||
arguments[1] = data
|
||||
res(arguments)
|
||||
end
|
||||
|
||||
local get_bans = function(count_data, arguments)
|
||||
local res, page, order_by, keyword, current_time = unpack(arguments)
|
||||
local count = count_data.count
|
||||
|
||||
local current_page
|
||||
if page < 1 then
|
||||
page, current_page = 1, 1
|
||||
end
|
||||
|
||||
local pages_count = get_pages_count(count)
|
||||
if page > pages_count then
|
||||
page, current_page = pages_count, pages_count
|
||||
end
|
||||
|
||||
local query = [[
|
||||
SELECT
|
||||
`sam_bans`.*,
|
||||
IFNULL(`p1`.`name`, '') AS `name`,
|
||||
IFNULL(`p2`.`name`, '') AS `admin_name`
|
||||
FROM
|
||||
`sam_bans`
|
||||
LEFT OUTER JOIN
|
||||
`sam_players` AS `p1`
|
||||
ON
|
||||
`sam_bans`.`steamid` = `p1`.`steamid`
|
||||
LEFT OUTER JOIN
|
||||
`sam_players` AS `p2`
|
||||
ON
|
||||
`sam_bans`.`admin` = `p2`.`steamid`
|
||||
WHERE
|
||||
(`sam_bans`.`unban_date` >= %d OR `sam_bans`.`unban_date` = 0)]]
|
||||
|
||||
query = query:format(current_time)
|
||||
|
||||
if keyword then
|
||||
query = query .. " AND `sam_bans`.`steamid` LIKE " .. SQL.Escape("%" .. keyword .. "%")
|
||||
end
|
||||
|
||||
local offset = math.abs(limit * (page - 1))
|
||||
query = query .. ([[
|
||||
ORDER BY
|
||||
`sam_bans`.`id` %s
|
||||
LIMIT
|
||||
%d OFFSET %d]]):format(order_by, limit, offset)
|
||||
|
||||
SQL.Query(query, resolve_promise, nil, {res, count, current_page})
|
||||
end
|
||||
|
||||
netstream.async.Hook("SAM.GetBans", function(res, ply, page, order_by, keyword)
|
||||
if not isnumber(page) then return end
|
||||
if order_by ~= "ASC" and order_by ~= "DESC" then return end
|
||||
if keyword ~= nil and not sam.isstring(keyword) then return end
|
||||
|
||||
get_page_count(res, get_bans, page, order_by, keyword)
|
||||
end, check)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local GetColor = SUI.GetColor
|
||||
local Line = sui.TDLib.LibClasses.Line
|
||||
|
||||
local COLUMN_FONT = SUI.CreateFont("Column", "Roboto", 18)
|
||||
local LINE_FONT = SUI.CreateFont("Line", "Roboto", 16)
|
||||
local NEXT_FONT = SUI.CreateFont("NextButton", "Roboto", 18)
|
||||
|
||||
sam.menu.add_tab("https://raw.githubusercontent.com/Srlion/Addons-Data/main/icons/sam/ban-user.png", function(column_sheet)
|
||||
local refresh, pages
|
||||
local current_page, current_order, keyword = nil, "DESC", nil
|
||||
|
||||
local bans_body = column_sheet:Add("Panel")
|
||||
bans_body:Dock(FILL)
|
||||
bans_body:DockMargin(0, 1, 0, 0)
|
||||
bans_body:DockPadding(10, 10, 10, 10)
|
||||
|
||||
local toggle_loading, is_loading = sam.menu.add_loading_panel(bans_body)
|
||||
|
||||
local title = bans_body:Add("SAM.Label")
|
||||
title:Dock(TOP)
|
||||
title:SetFont(SAM_TAB_TITLE_FONT)
|
||||
title:SetText("Bans")
|
||||
title:SetTextColor(GetColor("menu_tabs_title"))
|
||||
title:SizeToContents()
|
||||
|
||||
local total = bans_body:Add("SAM.Label")
|
||||
total:Dock(TOP)
|
||||
total:DockMargin(0, 6, 0, 0)
|
||||
total:SetFont(SAM_TAB_DESC_FONT)
|
||||
total:SetText("60 total bans")
|
||||
total:SetTextColor(GetColor("menu_tabs_title"))
|
||||
total:SetPos(10, SUI.Scale(40))
|
||||
total:SizeToContents()
|
||||
|
||||
do
|
||||
local container = bans_body:Add("SAM.Panel")
|
||||
container:Dock(TOP)
|
||||
container:DockMargin(0, 6, 10, 0)
|
||||
container:SetTall(30)
|
||||
|
||||
local sort_order = container:Add("SAM.ComboBox")
|
||||
sort_order:Dock(RIGHT)
|
||||
sort_order:SetWide(96)
|
||||
sort_order:SetValue("Desc")
|
||||
sort_order:AddChoice("Desc")
|
||||
sort_order:AddChoice("Asc")
|
||||
|
||||
function sort_order:OnSelect(_, value)
|
||||
value = value:upper()
|
||||
if current_order ~= value then
|
||||
current_order = value
|
||||
refresh()
|
||||
end
|
||||
end
|
||||
|
||||
local search_entry = container:Add("SAM.TextEntry")
|
||||
search_entry:Dock(LEFT)
|
||||
search_entry:SetNoBar(true)
|
||||
search_entry:SetPlaceholder("Search...")
|
||||
search_entry:SetRadius(4)
|
||||
search_entry:SetWide(220)
|
||||
|
||||
function search_entry:OnEnter()
|
||||
local value = self:GetValue()
|
||||
if keyword ~= value then
|
||||
keyword = value ~= "" and value or nil
|
||||
refresh()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Line(bans_body, nil, -5, 15, -5, 0)
|
||||
|
||||
do
|
||||
local columns = bans_body:Add("Panel")
|
||||
columns:Dock(TOP)
|
||||
columns:DockMargin(0, 10, 0, 0)
|
||||
|
||||
local info = columns:Add("SAM.Label")
|
||||
info:Dock(LEFT)
|
||||
info:DockMargin(4, 0, 0, 0)
|
||||
info:SetFont(COLUMN_FONT)
|
||||
info:SetText("Player")
|
||||
info:SetTextColor(GetColor("player_list_titles"))
|
||||
info:SetWide(SUI.Scale(280) + SUI.Scale(34))
|
||||
info:SizeToContentsY(3)
|
||||
|
||||
local time_left = columns:Add("SAM.Label")
|
||||
time_left:Dock(LEFT)
|
||||
time_left:DockMargin(-4, 0, 0, 0)
|
||||
time_left:SetFont(COLUMN_FONT)
|
||||
time_left:SetText("Time Left")
|
||||
time_left:SetTextColor(GetColor("player_list_titles"))
|
||||
time_left:SetWide(SUI.Scale(180))
|
||||
time_left:SizeToContentsY(3)
|
||||
|
||||
local reason = columns:Add("SAM.Label")
|
||||
reason:Dock(LEFT)
|
||||
reason:DockMargin(-4, 0, 0, 0)
|
||||
reason:SetFont(COLUMN_FONT)
|
||||
reason:SetText("Reason")
|
||||
reason:SetTextColor(GetColor("player_list_titles"))
|
||||
reason:SetWide(SUI.Scale(280))
|
||||
reason:SizeToContentsY(3)
|
||||
|
||||
columns:SizeToChildren(false, true)
|
||||
end
|
||||
|
||||
local body = bans_body:Add("SAM.ScrollPanel")
|
||||
body:Dock(FILL)
|
||||
body:DockMargin(0, 10, 0, 0)
|
||||
body:SetVBarPadding(6)
|
||||
|
||||
local set_data = function(data)
|
||||
body:GetCanvas():Clear()
|
||||
body.VBar.Scroll = 0
|
||||
|
||||
local bans, bans_count, current_page_2 = unpack(data)
|
||||
total:SetText(bans_count .. " total bans")
|
||||
|
||||
pages = get_pages_count(bans_count)
|
||||
current_page.i = pages == 0 and 0 or current_page_2 or current_page.i
|
||||
current_page:SetText(current_page.i .. "/" .. pages)
|
||||
|
||||
body:Line()
|
||||
|
||||
for k, v in ipairs(bans) do
|
||||
local line = body:Add("SAM.PlayerLine")
|
||||
line:DockMargin(0, 0, 0, 10)
|
||||
|
||||
local name = v.name ~= "" and v.name or nil
|
||||
local admin_name = v.admin_name ~= "" and v.admin_name or nil
|
||||
line:SetInfo({
|
||||
steamid = v.steamid,
|
||||
name = name,
|
||||
rank = admin_name or (v.admin == "Console" and "Console"),
|
||||
rank_bg = not admin_name and GetColor("player_list_console")
|
||||
})
|
||||
|
||||
local unban_date = tonumber(v.unban_date)
|
||||
local time_left = line:Add("SAM.Label")
|
||||
time_left:Dock(LEFT)
|
||||
time_left:DockMargin(-3, 0, 0, 0)
|
||||
time_left:SetFont(LINE_FONT)
|
||||
time_left:SetText(unban_date == 0 and "Never" or sam.reverse_parse_length((unban_date - os.time()) / 60))
|
||||
time_left:SetTextColor(GetColor("player_list_data"))
|
||||
time_left:SetContentAlignment(4)
|
||||
time_left:SetWide(SUI.Scale(180))
|
||||
|
||||
local reason = line:Add("SAM.Label")
|
||||
reason:Dock(LEFT)
|
||||
reason:DockMargin(4, 0, 0, 0)
|
||||
reason:SetFont(LINE_FONT)
|
||||
reason:SetText(v.reason)
|
||||
reason:SetTextColor(GetColor("player_list_data"))
|
||||
reason:SetContentAlignment(4)
|
||||
reason:SetWrap(true)
|
||||
reason:SetWide(SUI.Scale(200))
|
||||
|
||||
local old_tall = line.size
|
||||
function reason:PerformLayout()
|
||||
local _, h = self:GetTextSize()
|
||||
if old_tall < h then
|
||||
line:SetTall(h)
|
||||
end
|
||||
end
|
||||
|
||||
local but = line:Actions()
|
||||
but:On("DoClick", function()
|
||||
local dmenu = vgui.Create("SAM.Menu")
|
||||
dmenu:SetInternal(but)
|
||||
if name then
|
||||
dmenu:AddOption("Copy Name", function()
|
||||
SetClipboardText(name)
|
||||
end)
|
||||
end
|
||||
dmenu:AddOption("Copy SteamID", function()
|
||||
SetClipboardText(v.steamid)
|
||||
end)
|
||||
dmenu:AddOption("Copy Reason", function()
|
||||
SetClipboardText(v.reason)
|
||||
end)
|
||||
dmenu:AddOption("Copy Time Left", function()
|
||||
SetClipboardText(time_left:GetText())
|
||||
end)
|
||||
|
||||
if v.admin ~= "Console" then
|
||||
dmenu:AddSpacer()
|
||||
|
||||
if admin_name then
|
||||
dmenu:AddOption("Copy Admin Name", function()
|
||||
SetClipboardText(admin_name)
|
||||
end)
|
||||
end
|
||||
|
||||
dmenu:AddOption("Copy Admin SteamID", function()
|
||||
SetClipboardText(v.admin)
|
||||
end)
|
||||
end
|
||||
|
||||
if LocalPlayer():HasPermission("unban") then
|
||||
dmenu:AddSpacer()
|
||||
dmenu:AddOption("Unban", function()
|
||||
local user = name and ("%s (%s)"):format(name, v.steamid) or v.steamid
|
||||
local querybox = vgui.Create("SAM.QueryBox")
|
||||
querybox:SetWide(350)
|
||||
querybox:SetTitle(user)
|
||||
|
||||
local check = querybox:Add("SAM.Label")
|
||||
check:SetText(sui.wrap_text("Are you sure that you want to unban\n" .. user, LINE_FONT, SUI.Scale(350)))
|
||||
check:SetFont(LINE_FONT)
|
||||
check:SizeToContents()
|
||||
|
||||
querybox:Done()
|
||||
querybox.save:SetEnabled(true)
|
||||
querybox.save:SetText("UNBAN")
|
||||
|
||||
querybox.save:SetContained(false)
|
||||
querybox.save:SetColors(GetColor("query_box_cancel"), GetColor("query_box_cancel_text"))
|
||||
|
||||
querybox.cancel:SetContained(true)
|
||||
querybox.cancel:SetColors()
|
||||
|
||||
querybox:SetCallback(function()
|
||||
RunConsoleCommand("sam", "unban", v.steamid)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
dmenu:Open()
|
||||
end)
|
||||
|
||||
body:Line()
|
||||
end
|
||||
|
||||
body:InvalidateLayout(true)
|
||||
body:GetCanvas():InvalidateLayout(true)
|
||||
end
|
||||
|
||||
refresh = function()
|
||||
if not is_loading() and LocalPlayer():HasPermission("manage_bans") then
|
||||
local refresh_query = netstream.async.Start("SAM.GetBans", toggle_loading, current_page.i, current_order, keyword)
|
||||
refresh_query:done(set_data)
|
||||
end
|
||||
end
|
||||
|
||||
local bottom_panel = bans_body:Add("SAM.Panel")
|
||||
bottom_panel:Dock(BOTTOM)
|
||||
bottom_panel:DockMargin(0, 6, 0, 0)
|
||||
bottom_panel:SetTall(30)
|
||||
bottom_panel:Background(GetColor("page_switch_bg"))
|
||||
|
||||
local previous_page = bottom_panel:Add("SAM.Button")
|
||||
previous_page:Dock(LEFT)
|
||||
previous_page:SetWide(30)
|
||||
previous_page:SetText("<")
|
||||
previous_page:SetFont(NEXT_FONT)
|
||||
|
||||
previous_page:On("DoClick", function()
|
||||
if current_page.i <= 1 then return end
|
||||
|
||||
current_page.i = current_page.i - 1
|
||||
refresh()
|
||||
end)
|
||||
|
||||
current_page = bottom_panel:Add("SAM.Label")
|
||||
current_page:Dock(FILL)
|
||||
current_page:SetContentAlignment(5)
|
||||
current_page:SetFont(SAM_TAB_DESC_FONT)
|
||||
current_page:SetText("loading...")
|
||||
current_page.i = 1
|
||||
|
||||
local next_page = bottom_panel:Add("SAM.Button")
|
||||
next_page:Dock(RIGHT)
|
||||
next_page:SetWide(30)
|
||||
next_page:SetText(">")
|
||||
next_page:SetFont(NEXT_FONT)
|
||||
|
||||
next_page:On("DoClick", function()
|
||||
if current_page.i == pages then return end
|
||||
|
||||
current_page.i = current_page.i + 1
|
||||
refresh()
|
||||
end)
|
||||
|
||||
function bottom_panel:Think()
|
||||
next_page:SetEnabled(current_page.i ~= pages)
|
||||
previous_page:SetEnabled(current_page.i > 1)
|
||||
end
|
||||
|
||||
for k, v in ipairs({"SAM.BannedPlayer", "SAM.BannedSteamID", "SAM.EditedBan", "SAM.UnbannedSteamID"}) do
|
||||
hook.Add(v, "SAM.MenuBans", function()
|
||||
if IsValid(body) then
|
||||
refresh()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
refresh()
|
||||
|
||||
return bans_body
|
||||
end, function()
|
||||
return LocalPlayer():HasPermission("manage_bans")
|
||||
end, 4)
|
||||
233
lua/sam/menu/tabs/commands.lua
Normal file
233
lua/sam/menu/tabs/commands.lua
Normal file
@@ -0,0 +1,233 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
if SAM_LOADED then return end
|
||||
if SERVER then return end
|
||||
|
||||
local sam = sam
|
||||
local SUI = sam.SUI
|
||||
local type = sam.type
|
||||
|
||||
local Line = sui.TDLib.LibClasses.Line
|
||||
|
||||
local COMMAND_HELP = SUI.CreateFont("CommandHelp", "Roboto", 14)
|
||||
local COMMAND_RUN = SUI.CreateFont("CommandRun", "Roboto Medium", 14)
|
||||
|
||||
sam.menu.add_tab("https://raw.githubusercontent.com/Srlion/Addons-Data/main/icons/sam/command_window.png", function(column_sheet)
|
||||
local tab_body = column_sheet:Add("Panel")
|
||||
tab_body:Dock(FILL)
|
||||
tab_body:DockMargin(0, 1, 0, 0)
|
||||
|
||||
do
|
||||
local title = tab_body:Add("SAM.Label")
|
||||
title:Dock(TOP)
|
||||
title:DockMargin(10, 10, 0, 0)
|
||||
title:SetFont(SAM_TAB_TITLE_FONT)
|
||||
title:SetText("Commands")
|
||||
title:SetTextColor(SUI.GetColor("menu_tabs_title"))
|
||||
title:SizeToContents()
|
||||
end
|
||||
|
||||
local body = tab_body:Add("Panel")
|
||||
body:Dock(FILL)
|
||||
body:DockMargin(10, 5, 10, 10)
|
||||
|
||||
Line(body)
|
||||
|
||||
local left_body = body:Add("SAM.Panel")
|
||||
left_body:Dock(LEFT)
|
||||
left_body:SetWide(148)
|
||||
|
||||
local search_entry = left_body:Add("SAM.TextEntry")
|
||||
search_entry:Dock(TOP)
|
||||
search_entry:SetNoBar(true)
|
||||
search_entry:SetPlaceholder("Search...")
|
||||
search_entry:SetRadius(4)
|
||||
search_entry:SetTall(27)
|
||||
|
||||
local category_list = left_body:Add("SAM.CollapseCategory")
|
||||
category_list:Dock(FILL)
|
||||
category_list:DockMargin(0, SUI.Scale(10), 0, 0)
|
||||
|
||||
local canvas = category_list:GetCanvas()
|
||||
|
||||
local commands_refresh = function()
|
||||
if not IsValid(category_list) then return end
|
||||
|
||||
canvas:Clear()
|
||||
table.Empty(category_list.items)
|
||||
table.Empty(category_list.categories)
|
||||
|
||||
for k, v in ipairs(sam.command.get_commands()) do
|
||||
if (v.permission and not LocalPlayer():HasPermission(v.permission)) or v.menu_hide then
|
||||
continue
|
||||
end
|
||||
|
||||
local item = category_list:add_item(v.name, v.category)
|
||||
item:InvalidateParent(true)
|
||||
item.help = v.help
|
||||
item.command = v
|
||||
|
||||
item.names = {v.name:lower()}
|
||||
for _, aliase in ipairs(v.aliases) do
|
||||
table.insert(item.names, aliase:lower())
|
||||
end
|
||||
end
|
||||
end
|
||||
commands_refresh()
|
||||
|
||||
do
|
||||
local hooks = {
|
||||
"SAM.CommandAdded", "SAM.CommandModified", "SAM.CommandRemoved",
|
||||
"SAM.RemovedPermission",
|
||||
{"SAM.ChangedPlayerRank", func = function(ply, rank, old_rank)
|
||||
if rank == old_rank then return end
|
||||
if ply == LocalPlayer() then
|
||||
commands_refresh()
|
||||
end
|
||||
end},
|
||||
{
|
||||
"SAM.RankPermissionGiven", "SAM.RankPermissionTaken", "SAM.ChangedInheritRank",
|
||||
func = function(rank)
|
||||
if rank == LocalPlayer():sam_getrank() then
|
||||
commands_refresh()
|
||||
end
|
||||
end
|
||||
},
|
||||
{
|
||||
"SAM.AddedPermission", "SAM.PermissionModified",
|
||||
func = function(_, _, rank)
|
||||
if rank == LocalPlayer():sam_getrank() then
|
||||
commands_refresh()
|
||||
end
|
||||
end
|
||||
}
|
||||
}
|
||||
for _, v in ipairs(hooks) do
|
||||
if type(v) == "table" then
|
||||
for _, v2 in ipairs(v) do
|
||||
hook.Add(v2, "SAM.Menu.RefreshCommands", v.func)
|
||||
end
|
||||
else
|
||||
hook.Add(v, "SAM.Menu.RefreshCommands", commands_refresh)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function search_entry:OnValueChange(text)
|
||||
category_list:Search(text:lower())
|
||||
end
|
||||
|
||||
do
|
||||
local line = Line(body, LEFT)
|
||||
line:DockMargin(10, 0, 10, 0)
|
||||
line:SetWide(1)
|
||||
end
|
||||
|
||||
local buttons = body:Add("SAM.ScrollPanel")
|
||||
buttons:Dock(FILL)
|
||||
|
||||
local childs = {}
|
||||
local pos = 0
|
||||
buttons:GetCanvas():On("OnChildAdded", function(s, child)
|
||||
child:Dock(TOP)
|
||||
child:DockMargin(0, 0, 0, 5)
|
||||
child:SetAlpha(0)
|
||||
child:SetVisible(false)
|
||||
table.insert(childs, child)
|
||||
|
||||
pos = pos + 1
|
||||
child:SetZPos(pos)
|
||||
end)
|
||||
|
||||
local run_command = buttons:Add("SAM.Button")
|
||||
run_command:Dock(TOP)
|
||||
run_command:SetTall(25)
|
||||
run_command:SetFont(COMMAND_RUN)
|
||||
run_command:SetZPos(100)
|
||||
run_command:SetEnabled(false)
|
||||
|
||||
run_command:On("DoClick", function(self)
|
||||
LocalPlayer():ConCommand("sam\"" .. self:GetText() .. "\"\"" .. table.concat(self.input_arguments, "\"\"") .. "\"")
|
||||
end)
|
||||
|
||||
local help = buttons:Add("SAM.Label")
|
||||
help:Dock(TOP)
|
||||
help:SetFont(COMMAND_HELP)
|
||||
help:SetZPos(101)
|
||||
help:SetWrap(true)
|
||||
help:SetAutoStretchVertical(true)
|
||||
|
||||
sam.menu.get():On("OnKeyCodePressed", function(s, key_code)
|
||||
if key_code == KEY_ENTER and IsValid(run_command) and run_command:IsEnabled() and run_command:IsMouseInputEnabled() and tab_body:IsVisible() then
|
||||
run_command:DoClick()
|
||||
end
|
||||
end)
|
||||
|
||||
function category_list:item_selected(item)
|
||||
local arguments = sam.command.get_arguments()
|
||||
local command = item.command
|
||||
local command_arguments = command.args
|
||||
local input_arguments = {}
|
||||
|
||||
for i = #childs, 3, -1 do
|
||||
local v = childs[i]
|
||||
if not v.no_change or not command:HasArg(v.no_change) then
|
||||
if v.no_remove ~= true then
|
||||
v:Remove()
|
||||
else
|
||||
v:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local NIL = {}
|
||||
for _, v in ipairs(command_arguments) do
|
||||
local func = arguments[v.name]["menu"]
|
||||
if not func then continue end
|
||||
|
||||
local i = table.insert(input_arguments, NIL)
|
||||
local p = func(function(allow)
|
||||
if not IsValid(run_command) then return end
|
||||
input_arguments[i] = allow == nil and NIL or allow
|
||||
for i_2 = 1, #input_arguments do
|
||||
if input_arguments[i_2] == NIL then
|
||||
run_command:SetEnabled(false)
|
||||
return
|
||||
end
|
||||
end
|
||||
run_command:SetEnabled(true)
|
||||
end, body, buttons, v, childs)
|
||||
if p then
|
||||
p:AnimatedSetVisible(true)
|
||||
end
|
||||
end
|
||||
|
||||
if #command_arguments == 0 then
|
||||
run_command:SetEnabled(true)
|
||||
end
|
||||
|
||||
run_command:SetText(command.name)
|
||||
run_command:AnimatedSetVisible(true)
|
||||
run_command.input_arguments = input_arguments
|
||||
|
||||
if command.help then
|
||||
help:SetText(command.help)
|
||||
help:AnimatedSetVisible(true)
|
||||
help:SizeToContents()
|
||||
else
|
||||
help:AnimatedSetVisible(false)
|
||||
end
|
||||
|
||||
buttons:InvalidateLayout(true)
|
||||
end
|
||||
|
||||
return tab_body
|
||||
end, nil, 1)
|
||||
107
lua/sam/menu/tabs/config.lua
Normal file
107
lua/sam/menu/tabs/config.lua
Normal file
@@ -0,0 +1,107 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
if SAM_LOADED then return end
|
||||
|
||||
local sam = sam
|
||||
local config = sam.config
|
||||
|
||||
local tabs = {}
|
||||
if CLIENT then
|
||||
function config.add_tab(name, func, check, pos)
|
||||
local tab = {
|
||||
name = name,
|
||||
func = func,
|
||||
check = check,
|
||||
pos = pos
|
||||
}
|
||||
for k, v in ipairs(tabs) do
|
||||
if v.name == name then
|
||||
tabs[k] = tab
|
||||
return
|
||||
end
|
||||
end
|
||||
table.insert(tabs, tab)
|
||||
end
|
||||
end
|
||||
|
||||
for _, f in ipairs(file.Find("sam/menu/tabs/config/*.lua", "LUA")) do
|
||||
sam.load_file("sam/menu/tabs/config/" .. f, "cl_")
|
||||
end
|
||||
|
||||
if SERVER then return end
|
||||
|
||||
local SUI = sam.SUI
|
||||
local GetColor = SUI.GetColor
|
||||
local Line = sui.TDLib.LibClasses.Line
|
||||
|
||||
sam.menu.add_tab("https://raw.githubusercontent.com/Srlion/Addons-Data/main/icons/sam/config.png", function(column_sheet)
|
||||
local tab_body = column_sheet:Add("Panel")
|
||||
tab_body:Dock(FILL)
|
||||
tab_body:DockMargin(0, 1, 0, 0)
|
||||
|
||||
do
|
||||
local title = tab_body:Add("SAM.Label")
|
||||
title:Dock(TOP)
|
||||
title:DockMargin(10, 10, 0, 0)
|
||||
title:SetFont(SAM_TAB_TITLE_FONT)
|
||||
title:SetText("Config")
|
||||
title:SetTextColor(GetColor("menu_tabs_title"))
|
||||
title:SizeToContents()
|
||||
|
||||
local total = tab_body:Add("SAM.Label")
|
||||
total:Dock(TOP)
|
||||
total:DockMargin(10, 6, 0, 0)
|
||||
total:SetFont(SAM_TAB_DESC_FONT)
|
||||
total:SetText("Some settings may require a server restart")
|
||||
total:SetTextColor(GetColor("menu_tabs_title"))
|
||||
total:SetPos(10, SUI.Scale(40))
|
||||
total:SizeToContents()
|
||||
end
|
||||
|
||||
local body = tab_body:Add("Panel")
|
||||
body:Dock(FILL)
|
||||
body:DockMargin(10, 5, 10, 10)
|
||||
|
||||
Line(body, nil, 0, 0, 0, 10)
|
||||
|
||||
local sheet = body:Add("SAM.PropertySheet")
|
||||
sheet:Dock(FILL)
|
||||
sheet:InvalidateParent(true)
|
||||
sheet:InvalidateLayout(true)
|
||||
|
||||
local sheets = {}
|
||||
for _, v in SortedPairsByMemberValue(tabs, "pos") do
|
||||
sheets[v.name] = sheet:AddSheet(v.name, v.func)
|
||||
end
|
||||
|
||||
local tab_scroller = sheet.tab_scroller:GetCanvas()
|
||||
function tab_body.Think()
|
||||
for _, v in ipairs(tabs) do
|
||||
local tab = sheets[v.name]
|
||||
if v.check and not v.check() then
|
||||
if tab:IsVisible() then
|
||||
tab:SetVisible(false)
|
||||
if sheet:GetActiveTab() == tab then
|
||||
sheet:SetActiveTab(sheet.tabs[1])
|
||||
end
|
||||
tab_scroller:InvalidateLayout()
|
||||
end
|
||||
elseif not tab:IsVisible() then
|
||||
tab:SetVisible(true)
|
||||
tab_scroller:InvalidateLayout()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return tab_body
|
||||
end, function()
|
||||
return LocalPlayer():HasPermission("manage_config")
|
||||
end, 5)
|
||||
171
lua/sam/menu/tabs/config/reports.lua
Normal file
171
lua/sam/menu/tabs/config/reports.lua
Normal file
@@ -0,0 +1,171 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
if SAM_LOADED then return end
|
||||
|
||||
local sam = sam
|
||||
local config = sam.config
|
||||
|
||||
local not_empty = function(s)
|
||||
return s and s ~= ""
|
||||
end
|
||||
|
||||
local number_entry = function(setting, config_key, default)
|
||||
local entry = setting:Add("SAM.TextEntry")
|
||||
entry:SetWide(50)
|
||||
entry:SetPlaceholder("")
|
||||
entry:SetBackground(Color(34, 34, 34))
|
||||
entry:SetNumeric(true)
|
||||
entry:DisallowFloats()
|
||||
entry:DisallowNegative()
|
||||
entry:SetCheck(not_empty)
|
||||
entry:SetConfig(config_key, default)
|
||||
|
||||
return entry
|
||||
end
|
||||
|
||||
config.add_tab("Reports", function(parent)
|
||||
local body = parent:Add("SAM.ScrollPanel")
|
||||
body:Dock(FILL)
|
||||
body:LineMargin(0, 6, 0, 0)
|
||||
|
||||
local i = 0
|
||||
body:GetCanvas():On("OnChildAdded", function(s, child)
|
||||
i = i + 1
|
||||
child:SetZPos(i)
|
||||
|
||||
if not body.making_line then
|
||||
body:Line()
|
||||
end
|
||||
end)
|
||||
|
||||
do
|
||||
local setting = body:Add("SAM.LabelPanel")
|
||||
setting:Dock(TOP)
|
||||
setting:SetLabel("Enable")
|
||||
setting:DockMargin(8, 6, 8, 0)
|
||||
|
||||
local enable = setting:Add("SAM.ToggleButton")
|
||||
enable:SetConfig("Reports", true)
|
||||
end
|
||||
|
||||
do
|
||||
local setting = body:Add("SAM.LabelPanel")
|
||||
setting:Dock(TOP)
|
||||
setting:SetLabel("Commands")
|
||||
setting:DockMargin(8, 6, 8, 0)
|
||||
|
||||
local entry = setting:Add("SAM.TextEntry")
|
||||
entry:SetWide(200)
|
||||
entry:SetNoBar(true)
|
||||
entry:SetPlaceholder("")
|
||||
entry:SetMultiline(true)
|
||||
entry:SetConfig("Reports.Commands")
|
||||
entry.no_scale = true
|
||||
|
||||
function entry:OnValueChange()
|
||||
self:SetTall(self:GetNumLines() * (sam.SUI.Scale(16) --[[font size]] + 1) + 1 + 2)
|
||||
end
|
||||
entry:OnValueChange()
|
||||
end
|
||||
|
||||
do
|
||||
local setting = body:Add("SAM.LabelPanel")
|
||||
setting:Dock(TOP)
|
||||
setting:SetLabel("Max Reports (Number of reports that can show on your screen)")
|
||||
setting:DockMargin(8, 6, 8, 0)
|
||||
|
||||
number_entry(setting, "Reports.MaxReports", 4)
|
||||
end
|
||||
|
||||
do
|
||||
local setting = body:Add("SAM.LabelPanel")
|
||||
setting:Dock(TOP)
|
||||
setting:SetLabel("Auto Close Time (Time to wait before automatically closing claimed reports)")
|
||||
setting:DockMargin(8, 6, 8, 0)
|
||||
|
||||
local entry = setting:Add("SAM.TextEntry")
|
||||
entry:SetWide(70)
|
||||
entry:SetNoBar(false)
|
||||
entry:SetPlaceholder("")
|
||||
entry:SetCheck(function(time)
|
||||
time = sam.parse_length(time)
|
||||
if not time then
|
||||
return false
|
||||
end
|
||||
end)
|
||||
entry:SetConfig("Reports.AutoCloseTime", "10m")
|
||||
end
|
||||
|
||||
do
|
||||
local setting = body:Add("SAM.LabelPanel")
|
||||
setting:Dock(TOP)
|
||||
setting:SetLabel("Always Show (Show the popups even if you are not on duty)")
|
||||
setting:DockMargin(8, 6, 8, 0)
|
||||
|
||||
local enable = setting:Add("SAM.ToggleButton")
|
||||
enable:SetConfig("Reports.AlwaysShow", true)
|
||||
end
|
||||
|
||||
do
|
||||
local setting = body:Add("SAM.LabelPanel")
|
||||
setting:Dock(TOP)
|
||||
setting:SetLabel("On Duty Jobs")
|
||||
setting:DockMargin(8, 6, 8, 0)
|
||||
|
||||
local entry = setting:Add("SAM.TextEntry")
|
||||
entry:SetWide(300)
|
||||
entry:SetNoBar(true)
|
||||
entry:SetPlaceholder("")
|
||||
entry:SetMultiline(true)
|
||||
entry:SetConfig("Reports.DutyJobs", "")
|
||||
entry.no_scale = true
|
||||
|
||||
function entry:OnValueChange()
|
||||
self:SetTall(self:GetNumLines() * (sam.SUI.Scale(16) --[[font size]] + 1) + 1 + 2)
|
||||
end
|
||||
entry:OnValueChange()
|
||||
end
|
||||
|
||||
do
|
||||
local setting = body:Add("SAM.LabelPanel")
|
||||
setting:Dock(TOP)
|
||||
setting:SetLabel("Position")
|
||||
setting:DockMargin(8, 6, 8, 0)
|
||||
|
||||
local combo = setting:Add("SAM.ComboBox")
|
||||
combo:SetWide(60)
|
||||
combo:AddChoice("Left", nil, true)
|
||||
combo:AddChoice("Right")
|
||||
combo:SetConfig("Reports.Position", "Left")
|
||||
end
|
||||
|
||||
do
|
||||
local setting = body:Add("SAM.LabelPanel")
|
||||
setting:Dock(TOP)
|
||||
setting:SetLabel("X Padding")
|
||||
setting:DockMargin(8, 6, 8, 0)
|
||||
|
||||
number_entry(setting, "Reports.XPadding", 5)
|
||||
end
|
||||
|
||||
do
|
||||
local setting = body:Add("SAM.LabelPanel")
|
||||
setting:Dock(TOP)
|
||||
setting:SetLabel("Y Padding")
|
||||
setting:DockMargin(8, 6, 8, 0)
|
||||
|
||||
number_entry(setting, "Reports.YPadding", 5)
|
||||
end
|
||||
|
||||
return body
|
||||
end, function()
|
||||
return LocalPlayer():HasPermission("manage_config")
|
||||
end, 2)
|
||||
42
lua/sam/menu/tabs/config/server.lua
Normal file
42
lua/sam/menu/tabs/config/server.lua
Normal file
@@ -0,0 +1,42 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
if SAM_LOADED then return end
|
||||
|
||||
local sam = sam
|
||||
local config = sam.config
|
||||
|
||||
config.add_tab("Server", function(parent)
|
||||
local server_body = parent:Add("SAM.ScrollPanel")
|
||||
server_body:Dock(FILL)
|
||||
server_body:LineMargin(0, 6, 0, 0)
|
||||
|
||||
local i = 0
|
||||
server_body:GetCanvas():On("OnChildAdded", function(s, child)
|
||||
i = i + 1
|
||||
child:SetZPos(i)
|
||||
end)
|
||||
|
||||
for k, v in ipairs(sam.config.get_menu_settings()) do
|
||||
local panel = v.func(server_body)
|
||||
if ispanel(panel) then
|
||||
local setting = server_body:Add("SAM.LabelPanel")
|
||||
setting:DockMargin(8, 6, 8, 0)
|
||||
setting:SetLabel(v.title)
|
||||
setting:SetPanel(panel)
|
||||
end
|
||||
|
||||
server_body:Line()
|
||||
end
|
||||
|
||||
return server_body
|
||||
end, function()
|
||||
return LocalPlayer():HasPermission("manage_config")
|
||||
end, 1)
|
||||
462
lua/sam/menu/tabs/players.lua
Normal file
462
lua/sam/menu/tabs/players.lua
Normal file
@@ -0,0 +1,462 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
if SAM_LOADED then return end
|
||||
|
||||
local sam = sam
|
||||
local SQL = sam.SQL
|
||||
local SUI = sam.SUI
|
||||
local netstream = sam.netstream
|
||||
|
||||
sam.permissions.add("manage_players", nil, "superadmin")
|
||||
|
||||
local get_pages_count = function(count)
|
||||
count = count / 35
|
||||
local i2 = math.floor(count)
|
||||
return count ~= i2 and i2 + 1 or count
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
local check = function(ply)
|
||||
return ply:HasPermission("manage_players") and ply:sam_check_cooldown("MenuViewPlayers", 0.1)
|
||||
end
|
||||
|
||||
local limit = 35
|
||||
|
||||
local get_page_count = function(callback, res, page, column, order_by, sort_by, keyword)
|
||||
local query = [[
|
||||
SELECT
|
||||
COUNT(`steamid`) AS `count`
|
||||
FROM
|
||||
`sam_players`]]
|
||||
if keyword then
|
||||
if column == "steamid" and sam.is_steamid64(keyword) then
|
||||
keyword = util.SteamIDFrom64(keyword)
|
||||
end
|
||||
|
||||
query = string.format("%s WHERE `%s` LIKE %s", query, column, SQL.Escape("%" .. keyword .. "%"))
|
||||
end
|
||||
SQL.Query(query, callback, true, {res, page, column, order_by, sort_by, keyword})
|
||||
end
|
||||
|
||||
local valid_columns = {
|
||||
steamid = true,
|
||||
name = true,
|
||||
rank = true
|
||||
}
|
||||
|
||||
local valid_sorts = {
|
||||
id = true,
|
||||
name = true,
|
||||
rank = true,
|
||||
play_time = true,
|
||||
last_join = true
|
||||
}
|
||||
|
||||
local resolve_promise = function(data, arguments)
|
||||
local res = arguments[1]
|
||||
arguments[1] = data
|
||||
res(arguments)
|
||||
end
|
||||
|
||||
local get_players = function(count_data, arguments)
|
||||
local res, page, column, order_by, sort_by, keyword = unpack(arguments)
|
||||
local count = count_data.count
|
||||
|
||||
local current_page
|
||||
if page < 1 then
|
||||
page, current_page = 1, 1
|
||||
end
|
||||
|
||||
local pages_count = get_pages_count(count)
|
||||
if page > pages_count then
|
||||
page, current_page = pages_count, pages_count
|
||||
end
|
||||
|
||||
local query = [[
|
||||
SELECT
|
||||
`steamid`,
|
||||
`name`,
|
||||
`rank`,
|
||||
`expiry_date`,
|
||||
`first_join`,
|
||||
`last_join`,
|
||||
`play_time`
|
||||
FROM
|
||||
`sam_players`
|
||||
]]
|
||||
|
||||
local args = {}
|
||||
|
||||
if keyword then
|
||||
args[1] = column
|
||||
args[2] = "%" .. keyword .. "%"
|
||||
|
||||
query = query .. [[
|
||||
WHERE
|
||||
`{1f}` LIKE {2}
|
||||
]]
|
||||
end
|
||||
|
||||
args[3] = sort_by
|
||||
if order_by == "DESC" then
|
||||
query = query .. [[
|
||||
ORDER BY `{3f}` DESC
|
||||
]]
|
||||
else
|
||||
query = query .. [[
|
||||
ORDER BY `{3f}` ASC
|
||||
]]
|
||||
end
|
||||
|
||||
args[4] = limit
|
||||
args[5] = math.abs(limit * (page - 1))
|
||||
|
||||
query = query .. [[
|
||||
LIMIT {4} OFFSET {5}
|
||||
]]
|
||||
|
||||
SQL.FQuery(query, args, resolve_promise, false, {res, count, current_page})
|
||||
end
|
||||
|
||||
netstream.async.Hook("SAM.GetPlayers", function(res, ply, page, column, order_by, sort_by, keyword)
|
||||
if not isnumber(page) then return end
|
||||
if not valid_columns[column] then return end
|
||||
if order_by ~= "ASC" and order_by ~= "DESC" then return end
|
||||
if not valid_sorts[sort_by] then return end
|
||||
if keyword ~= nil and not sam.isstring(keyword) then return end
|
||||
|
||||
get_page_count(get_players, res, page, column, order_by, sort_by, keyword)
|
||||
end, check)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local GetColor = SUI.GetColor
|
||||
local Line = sui.TDLib.LibClasses.Line
|
||||
|
||||
local COLUMN_FONT = SUI.CreateFont("Column", "Roboto", 18)
|
||||
local LINE_FONT = SUI.CreateFont("Line", "Roboto", 16)
|
||||
local NEXT_FONT = SUI.CreateFont("NextButton", "Roboto", 18)
|
||||
|
||||
local button_click = function(s)
|
||||
local v = s.v
|
||||
|
||||
local dmenu = vgui.Create("SAM.Menu")
|
||||
dmenu:SetInternal(s)
|
||||
if v.name and v.name ~= "" then
|
||||
dmenu:AddOption("Copy Name", function()
|
||||
SetClipboardText(v.name)
|
||||
end)
|
||||
end
|
||||
|
||||
dmenu:AddOption("Copy SteamID", function()
|
||||
SetClipboardText(v.steamid)
|
||||
end)
|
||||
|
||||
dmenu:AddOption("Copy Rank", function()
|
||||
SetClipboardText(v.rank)
|
||||
end)
|
||||
|
||||
dmenu:AddOption("Copy Play Time", function()
|
||||
SetClipboardText(sam.reverse_parse_length(tonumber(v.play_time) / 60))
|
||||
end)
|
||||
|
||||
dmenu:AddSpacer()
|
||||
|
||||
dmenu:AddOption("Change Rank", function()
|
||||
local querybox = vgui.Create("SAM.QueryBox")
|
||||
querybox:SetTitle(string.format("Change rank for '%s'", v.name or v.steamid))
|
||||
querybox:SetWide(360)
|
||||
|
||||
local ranks = querybox:Add("SAM.ComboBox")
|
||||
ranks:SetTall(28)
|
||||
|
||||
for rank_name in SortedPairsByMemberValue(sam.ranks.get_ranks(), "immunity", true) do
|
||||
if v.rank ~= rank_name then
|
||||
ranks:AddChoice(rank_name, nil, true)
|
||||
end
|
||||
end
|
||||
|
||||
querybox:Done()
|
||||
querybox.save:SetEnabled(true)
|
||||
|
||||
querybox:SetCallback(function()
|
||||
RunConsoleCommand("sam", "setrankid", v.steamid, ranks:GetValue())
|
||||
end)
|
||||
end)
|
||||
|
||||
dmenu:Open()
|
||||
end
|
||||
|
||||
sam.menu.add_tab("https://raw.githubusercontent.com/Srlion/Addons-Data/main/icons/sam/user.png", function(column_sheet)
|
||||
local refresh, pages
|
||||
local current_page, current_column, current_order, current_sort, keyword = nil, "steamid", "DESC", "id", nil
|
||||
|
||||
local players_body = column_sheet:Add("Panel")
|
||||
players_body:Dock(FILL)
|
||||
players_body:DockMargin(0, 1, 0, 0)
|
||||
players_body:DockPadding(10, 10, 10, 10)
|
||||
|
||||
local toggle_loading, is_loading = sam.menu.add_loading_panel(players_body)
|
||||
|
||||
local title = players_body:Add("SAM.Label")
|
||||
title:Dock(TOP)
|
||||
title:SetFont(SAM_TAB_TITLE_FONT)
|
||||
title:SetText("Players")
|
||||
title:SetTextColor(GetColor("menu_tabs_title"))
|
||||
title:SizeToContents()
|
||||
|
||||
local total = players_body:Add("SAM.Label")
|
||||
total:Dock(TOP)
|
||||
total:DockMargin(0, 6, 0, 0)
|
||||
total:SetFont(SAM_TAB_DESC_FONT)
|
||||
total:SetText("60 total players")
|
||||
total:SetTextColor(GetColor("menu_tabs_title"))
|
||||
total:SetPos(10, SUI.Scale(40))
|
||||
total:SizeToContents()
|
||||
|
||||
local search_entry
|
||||
do
|
||||
local container = players_body:Add("SAM.Panel")
|
||||
container:Dock(TOP)
|
||||
container:DockMargin(0, 6, 10, 0)
|
||||
container:SetTall(30)
|
||||
|
||||
local sort_by = container:Add("SAM.ComboBox")
|
||||
sort_by:Dock(RIGHT)
|
||||
sort_by:DockMargin(4, 0, 0, 0)
|
||||
sort_by:SetWide(106)
|
||||
sort_by:SetValue("Sort By (ID)")
|
||||
sort_by:AddChoice("ID")
|
||||
sort_by:AddChoice("Name")
|
||||
sort_by:AddChoice("Rank")
|
||||
sort_by:AddChoice("Play Time")
|
||||
|
||||
function sort_by:OnSelect(_, value)
|
||||
value = value:lower():gsub(" ", "_")
|
||||
if current_sort ~= value then
|
||||
current_sort = value
|
||||
refresh()
|
||||
end
|
||||
end
|
||||
|
||||
local sort_order = container:Add("SAM.ComboBox")
|
||||
sort_order:Dock(RIGHT)
|
||||
sort_order:SetWide(96)
|
||||
sort_order:SetValue("Desc")
|
||||
sort_order:AddChoice("Desc")
|
||||
sort_order:AddChoice("Asc")
|
||||
|
||||
function sort_order:OnSelect(_, value)
|
||||
value = value:upper()
|
||||
if current_order ~= value then
|
||||
current_order = value
|
||||
refresh()
|
||||
end
|
||||
end
|
||||
|
||||
local column = container:Add("SAM.ComboBox")
|
||||
column:Dock(RIGHT)
|
||||
column:DockMargin(0, 0, 4, 0)
|
||||
column:SetWide(140)
|
||||
|
||||
column:SetValue("Search (SteamID)")
|
||||
column:AddChoice("SteamID")
|
||||
column:AddChoice("Name")
|
||||
column:AddChoice("Rank")
|
||||
|
||||
function column:OnSelect(_, value)
|
||||
value = value:lower()
|
||||
if current_column ~= value then
|
||||
current_column = value
|
||||
refresh()
|
||||
end
|
||||
end
|
||||
|
||||
search_entry = container:Add("SAM.TextEntry")
|
||||
search_entry:Dock(LEFT)
|
||||
search_entry:SetNoBar(true)
|
||||
search_entry:SetPlaceholder("Search...")
|
||||
search_entry:SetRadius(4)
|
||||
search_entry:SetWide(220)
|
||||
|
||||
function search_entry:OnEnter(no_refresh)
|
||||
local value = self:GetValue()
|
||||
if keyword ~= value then
|
||||
keyword = value ~= "" and value or nil
|
||||
if not no_refresh then
|
||||
refresh()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Line(players_body, nil, -5, SUI.Scale(15), -5, 0)
|
||||
|
||||
do
|
||||
local columns = players_body:Add("Panel")
|
||||
columns:Dock(TOP)
|
||||
columns:DockMargin(0, 10, 0, 0)
|
||||
|
||||
local info = columns:Add("SAM.Label")
|
||||
info:Dock(LEFT)
|
||||
info:DockMargin(4, 0, 0, 0)
|
||||
info:SetFont(COLUMN_FONT)
|
||||
info:SetText("Player")
|
||||
info:SetTextColor(GetColor("player_list_titles"))
|
||||
info:SetWide(SUI.Scale(280) + SUI.Scale(34))
|
||||
info:SizeToContentsY(3)
|
||||
|
||||
local play_time = columns:Add("SAM.Label")
|
||||
play_time:Dock(LEFT)
|
||||
play_time:DockMargin(-4, 0, 0, 0)
|
||||
play_time:SetFont(COLUMN_FONT)
|
||||
play_time:SetText("Play Time")
|
||||
play_time:SetTextColor(GetColor("player_list_titles"))
|
||||
play_time:SetWide(SUI.Scale(180))
|
||||
play_time:SizeToContentsY(3)
|
||||
|
||||
local rank_expiry = columns:Add("SAM.Label")
|
||||
rank_expiry:Dock(LEFT)
|
||||
rank_expiry:DockMargin(-4, 0, 0, 0)
|
||||
rank_expiry:SetFont(COLUMN_FONT)
|
||||
rank_expiry:SetText("Rank Expiry")
|
||||
rank_expiry:SetTextColor(GetColor("player_list_titles"))
|
||||
rank_expiry:SetWide(SUI.Scale(280))
|
||||
rank_expiry:SizeToContentsY(3)
|
||||
|
||||
columns:SizeToChildren(false, true)
|
||||
end
|
||||
|
||||
local body = players_body:Add("SAM.ScrollPanel")
|
||||
body:Dock(FILL)
|
||||
body:DockMargin(0, 10, 0, 0)
|
||||
body:SetVBarPadding(6)
|
||||
|
||||
local set_data = function(data)
|
||||
body:GetCanvas():Clear()
|
||||
body.VBar.Scroll = 0
|
||||
|
||||
local players, players_count, current_page_2 = unpack(data)
|
||||
total:SetText(players_count .. " total players")
|
||||
|
||||
pages = get_pages_count(players_count)
|
||||
current_page.i = pages == 0 and 0 or current_page_2 or current_page.i
|
||||
current_page:SetText(current_page.i .. "/" .. pages)
|
||||
|
||||
body:Line()
|
||||
|
||||
for k, v in ipairs(players) do
|
||||
local line = body:Add("SAM.PlayerLine")
|
||||
line:DockMargin(0, 0, 0, 10)
|
||||
|
||||
local name = v.name ~= "" and v.name or nil
|
||||
line:SetInfo({
|
||||
steamid = v.steamid,
|
||||
name = name,
|
||||
rank = v.rank
|
||||
})
|
||||
|
||||
local play_time = line:Add("SAM.Label")
|
||||
play_time:Dock(LEFT)
|
||||
play_time:DockMargin(4, 0, 0, 0)
|
||||
play_time:SetFont(LINE_FONT)
|
||||
play_time:SetText(sam.reverse_parse_length(tonumber(v.play_time) / 60))
|
||||
play_time:SetTextColor(GetColor("player_list_data"))
|
||||
play_time:SetContentAlignment(4)
|
||||
play_time:SetWide(SUI.Scale(180))
|
||||
|
||||
local expiry_date = tonumber(v.expiry_date)
|
||||
local rank_expiry = line:Add("SAM.Label")
|
||||
rank_expiry:Dock(LEFT)
|
||||
rank_expiry:DockMargin(-3, 0, 0, 0)
|
||||
rank_expiry:SetFont(LINE_FONT)
|
||||
rank_expiry:SetText(expiry_date == 0 and "Never" or sam.reverse_parse_length((expiry_date - os.time()) / 60))
|
||||
rank_expiry:SetTextColor(GetColor("player_list_data"))
|
||||
rank_expiry:SetContentAlignment(4)
|
||||
rank_expiry:SizeToContents()
|
||||
|
||||
local but = line:Actions()
|
||||
but.v = v
|
||||
but:On("DoClick", button_click)
|
||||
|
||||
body:Line()
|
||||
end
|
||||
end
|
||||
|
||||
refresh = function()
|
||||
if not is_loading() and LocalPlayer():HasPermission("manage_players") then
|
||||
search_entry:OnEnter(true)
|
||||
local refresh_query = netstream.async.Start("SAM.GetPlayers", toggle_loading, current_page.i, current_column, current_order, current_sort, keyword)
|
||||
refresh_query:done(set_data)
|
||||
end
|
||||
end
|
||||
|
||||
local bottom_panel = players_body:Add("SAM.Panel")
|
||||
bottom_panel:Dock(BOTTOM)
|
||||
bottom_panel:DockMargin(0, 6, 0, 0)
|
||||
bottom_panel:SetTall(30)
|
||||
bottom_panel:Background(GetColor("page_switch_bg"))
|
||||
|
||||
local previous_page = bottom_panel:Add("SAM.Button")
|
||||
previous_page:Dock(LEFT)
|
||||
previous_page:SetWide(30)
|
||||
previous_page:SetText("<")
|
||||
previous_page:SetFont(NEXT_FONT)
|
||||
|
||||
previous_page:On("DoClick", function()
|
||||
if current_page.i <= 1 then return end
|
||||
|
||||
current_page.i = current_page.i - 1
|
||||
refresh()
|
||||
end)
|
||||
|
||||
current_page = bottom_panel:Add("SAM.Label")
|
||||
current_page:Dock(FILL)
|
||||
current_page:SetContentAlignment(5)
|
||||
current_page:SetFont(SAM_TAB_DESC_FONT)
|
||||
current_page:SetText("loading...")
|
||||
current_page.i = 1
|
||||
|
||||
local next_page = bottom_panel:Add("SAM.Button")
|
||||
next_page:Dock(RIGHT)
|
||||
next_page:SetWide(30)
|
||||
next_page:SetText(">")
|
||||
next_page:SetFont(NEXT_FONT)
|
||||
|
||||
next_page:On("DoClick", function()
|
||||
if current_page.i == pages then return end
|
||||
|
||||
current_page.i = current_page.i + 1
|
||||
refresh()
|
||||
end)
|
||||
|
||||
function bottom_panel:Think()
|
||||
next_page:SetEnabled(current_page.i ~= pages)
|
||||
previous_page:SetEnabled(current_page.i > 1)
|
||||
end
|
||||
|
||||
do
|
||||
local refresh_2 = function()
|
||||
timer.Simple(1, refresh)
|
||||
end
|
||||
|
||||
for k, v in ipairs({"SAM.AuthedPlayer", "SAM.ChangedPlayerRank", "SAM.ChangedSteamIDRank"}) do
|
||||
hook.Add(v, "SAM.MenuPlayers", refresh_2)
|
||||
end
|
||||
end
|
||||
|
||||
refresh()
|
||||
|
||||
return players_body
|
||||
end, function()
|
||||
return LocalPlayer():HasPermission("manage_players")
|
||||
end, 2)
|
||||
637
lua/sam/menu/tabs/ranks.lua
Normal file
637
lua/sam/menu/tabs/ranks.lua
Normal file
@@ -0,0 +1,637 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
if SAM_LOADED then return end
|
||||
if SERVER then return end
|
||||
|
||||
local sam = sam
|
||||
local SUI = sam.SUI
|
||||
|
||||
local GetColor = SUI.GetColor
|
||||
local Line = sui.TDLib.LibClasses.Line
|
||||
local AnimatedSetVisible = sui.TDLib.LibClasses.AnimatedSetVisible
|
||||
|
||||
local RANK_NAME = SUI.CreateFont("RankName", "Roboto Bold", 18)
|
||||
local RANK_INFO = SUI.CreateFont("RankInfo", "Roboto Medium", 12)
|
||||
|
||||
local CREATE_RANK = SUI.CreateFont("CreateRank", "Roboto Bold", 16, 200)
|
||||
local RANK_TITLE = SUI.CreateFont("RankTitle", "Roboto Bold", 20)
|
||||
|
||||
local rank_menu = function(rank, data)
|
||||
local valid = sui.valid_options()
|
||||
|
||||
local imm, banlim
|
||||
if rank then
|
||||
imm, banlim = data.immunity, data.ban_limit
|
||||
end
|
||||
|
||||
local edit_rank = vgui.Create("SAM.QueryBox")
|
||||
edit_rank:SetWide(470)
|
||||
edit_rank:SetTitle(rank and string.format("Edit Rank '%s'", rank) or "Create Rank")
|
||||
|
||||
local new_name = rank
|
||||
if not sam.ranks.is_default_rank(rank) then
|
||||
local name = edit_rank:Add("SAM.LabelPanel")
|
||||
name:SetLabel("Rank Name")
|
||||
|
||||
local entry = name:Add("SAM.TextEntry")
|
||||
entry:SetSize(210, 28)
|
||||
entry:SetNoBar(false)
|
||||
entry:SetPlaceholder("")
|
||||
entry:SetValue(rank or "")
|
||||
entry:SetCheck(function(_name)
|
||||
new_name = _name
|
||||
|
||||
if _name == rank then return end
|
||||
if _name == "" or sam.ranks.is_rank(_name) then
|
||||
return false
|
||||
end
|
||||
end)
|
||||
|
||||
valid.Add(entry)
|
||||
end
|
||||
|
||||
local new_immunity = imm
|
||||
do
|
||||
local immunity = edit_rank:Add("SAM.LabelPanel")
|
||||
immunity:SetLabel("Immunity (2~99)")
|
||||
immunity:DockMargin(0, 5, 0, 0)
|
||||
|
||||
local entry = immunity:Add("SAM.TextEntry")
|
||||
entry:SetSize(210, 28)
|
||||
entry:SetNumeric(true)
|
||||
entry:DisallowFloats(true)
|
||||
entry:DisallowNegative(true)
|
||||
entry:SetPlaceholder("")
|
||||
entry:SetValue(imm or "2")
|
||||
entry:SetCheck(function(_immunity)
|
||||
new_immunity = _immunity
|
||||
|
||||
if _immunity == "" then
|
||||
return false
|
||||
end
|
||||
|
||||
_immunity = tonumber(_immunity)
|
||||
new_immunity = _immunity
|
||||
if _immunity < 2 or _immunity > 99 then
|
||||
return false
|
||||
end
|
||||
end)
|
||||
|
||||
valid.Add(entry)
|
||||
end
|
||||
|
||||
local new_banlimit = banlim
|
||||
do
|
||||
local banlimit = edit_rank:Add("SAM.LabelPanel")
|
||||
banlimit:SetLabel("Ban Limit (1y 1mo 1w 1d 1h 1m)")
|
||||
banlimit:DockMargin(0, 5, 0, 0)
|
||||
|
||||
local entry = banlimit:Add("SAM.TextEntry")
|
||||
entry:SetSize(210, 28)
|
||||
entry:SetNoBar(false)
|
||||
entry:SetPlaceholder("")
|
||||
entry:SetValue(banlim and sam.reverse_parse_length(banlim) or "2w")
|
||||
entry:SetCheck(function(_banlimit)
|
||||
new_banlimit = sam.parse_length(_banlimit)
|
||||
if not new_banlimit and _banlimit ~= banlim then
|
||||
return false
|
||||
end
|
||||
end)
|
||||
|
||||
valid.Add(entry)
|
||||
end
|
||||
|
||||
local inherit = rank and sam.ranks.get_rank(rank).inherit or "user"
|
||||
local new_inherit = inherit
|
||||
do
|
||||
local inherits_from = edit_rank:Add("SAM.LabelPanel")
|
||||
inherits_from:SetLabel("Inherits From")
|
||||
inherits_from:DockMargin(0, 5, 0, 0)
|
||||
|
||||
local entry = inherits_from:Add("SAM.ComboBox")
|
||||
entry:SetSize(210, 28)
|
||||
entry:SetValue(inherit)
|
||||
|
||||
for name in SortedPairsByMemberValue(sam.ranks.get_ranks(), "immunity", true) do
|
||||
if name ~= rank and not sam.ranks.inherits_from(name, rank) then
|
||||
entry:AddChoice(name)
|
||||
end
|
||||
end
|
||||
|
||||
function entry:OnSelect(_, value)
|
||||
new_inherit = value
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
edit_rank:Done()
|
||||
edit_rank.save:SetEnabled(true)
|
||||
edit_rank.save:SetText("SAVE")
|
||||
|
||||
if rank then
|
||||
edit_rank:SetCallback(function()
|
||||
local to_run = {}
|
||||
|
||||
if new_immunity ~= imm then
|
||||
table.insert(to_run, {"changerankimmunity", rank, new_immunity})
|
||||
end
|
||||
|
||||
if new_banlimit ~= banlim then
|
||||
table.insert(to_run, {"changerankbanlimit", rank, new_banlimit})
|
||||
end
|
||||
|
||||
if new_inherit ~= inherit then
|
||||
table.insert(to_run, {"changeinherit", rank, new_inherit})
|
||||
end
|
||||
|
||||
if new_name ~= rank then
|
||||
table.insert(to_run, {"renamerank", rank, new_name})
|
||||
end
|
||||
sam.command.run_commands(to_run)
|
||||
end)
|
||||
else
|
||||
edit_rank:SetCallback(function()
|
||||
RunConsoleCommand("sam", "addrank", new_name, new_inherit, new_immunity, new_banlimit)
|
||||
end)
|
||||
end
|
||||
|
||||
function edit_rank.save:Think()
|
||||
self:SetEnabled(valid.IsValid())
|
||||
end
|
||||
end
|
||||
|
||||
sam.menu.add_tab("https://raw.githubusercontent.com/Srlion/Addons-Data/main/icons/sam/military_rank.png", function(column_sheet)
|
||||
local current_rank
|
||||
|
||||
local parent = column_sheet:Add("Panel")
|
||||
parent:Dock(FILL)
|
||||
parent:DockMargin(0, 1, 0, 0)
|
||||
|
||||
local title = parent:Add("SAM.Label")
|
||||
title:Dock(TOP)
|
||||
title:DockMargin(10, 10, 0, 0)
|
||||
title:SetFont(SAM_TAB_TITLE_FONT)
|
||||
title:SetText("Ranks")
|
||||
title:SetTextColor(GetColor("menu_tabs_title"))
|
||||
title:SizeToContents()
|
||||
|
||||
local total = parent:Add("SAM.Label")
|
||||
total:Dock(TOP)
|
||||
total:DockMargin(10, 6, 0, 0)
|
||||
total:SetFont(SAM_TAB_DESC_FONT)
|
||||
total:SetText(table.Count(sam.ranks.get_ranks()) .. " total ranks")
|
||||
total:SetTextColor(GetColor("menu_tabs_title"))
|
||||
total:SizeToContents()
|
||||
|
||||
local search_entry
|
||||
do
|
||||
local container = parent:Add("SAM.Panel")
|
||||
container:Dock(TOP)
|
||||
container:DockMargin(10, 6, 10, SUI.Scale(15))
|
||||
container:SetTall(30)
|
||||
|
||||
search_entry = container:Add("SAM.TextEntry")
|
||||
search_entry:Dock(LEFT)
|
||||
search_entry:SetNoBar(true)
|
||||
search_entry:SetPlaceholder("Search...")
|
||||
search_entry:SetRadius(4)
|
||||
search_entry:SetWide(220)
|
||||
end
|
||||
|
||||
local create_rank = parent:Add("SAM.Button")
|
||||
create_rank:SetFont(CREATE_RANK)
|
||||
create_rank:SetText("Create Rank")
|
||||
create_rank:Dock(BOTTOM)
|
||||
create_rank:DockMargin(10, 0, 10, 10)
|
||||
|
||||
create_rank:On("DoClick", function()
|
||||
rank_menu()
|
||||
end)
|
||||
|
||||
local right_body = parent:Add("Panel")
|
||||
right_body:Dock(RIGHT)
|
||||
right_body:DockMargin(0, 5, 10, 10)
|
||||
right_body:SetWide(0)
|
||||
right_body:SetZPos(-1)
|
||||
|
||||
local rank_title = right_body:Add("SAM.Label")
|
||||
rank_title:Dock(TOP)
|
||||
rank_title:DockMargin(0, 0, 0, 5)
|
||||
rank_title:SetFont(RANK_TITLE)
|
||||
rank_title:SetTextColor(GetColor("menu_tabs_title"))
|
||||
|
||||
local permissions_body = right_body:Add("SAM.CollapseCategory")
|
||||
permissions_body:Dock(FILL)
|
||||
permissions_body:GetCanvas():DockPadding(0, 0, 5, 0)
|
||||
|
||||
local function refresh_access()
|
||||
if not IsValid(current_rank) then return end
|
||||
|
||||
for k, v in ipairs(permissions_body.items) do
|
||||
AnimatedSetVisible(v.img, sam.ranks.has_permission(current_rank.name, v.name))
|
||||
end
|
||||
end
|
||||
|
||||
for k, v in ipairs({"SAM.ChangedInheritRank", "SAM.RankPermissionGiven", "SAM.RankPermissionTaken"}) do
|
||||
hook.Add(v, "SAM.Menu.RefreshPermissions ", refresh_access)
|
||||
end
|
||||
|
||||
local function sortFunc(a, b)
|
||||
if (a.category == b.category) then return a.name < b.name end
|
||||
|
||||
return a.category < b.category
|
||||
end
|
||||
|
||||
local function refresh_permissions()
|
||||
permissions_body:GetCanvas():Clear()
|
||||
table.Empty(permissions_body.items)
|
||||
table.Empty(permissions_body.categories)
|
||||
|
||||
local item_click = function(s)
|
||||
local rank = current_rank.name
|
||||
if not sam.ranks.has_permission(rank, s.name) then
|
||||
RunConsoleCommand("sam", "givepermission", rank, s.name)
|
||||
else
|
||||
RunConsoleCommand("sam", "takepermission", rank, s.name)
|
||||
end
|
||||
end
|
||||
|
||||
local permissions = sam.permissions.get()
|
||||
table.sort(permissions, sortFunc)
|
||||
for k, v in ipairs(permissions) do
|
||||
local item = permissions_body:add_item(v.name, v.category)
|
||||
item:SetContentAlignment(4)
|
||||
item:SetTextInset(6, 0)
|
||||
item:SizeToContentsY(SUI.Scale(10))
|
||||
item:SetZPos(k)
|
||||
item.name = v.name
|
||||
item.DoClick = item_click
|
||||
|
||||
local img = item:Add("SAM.Image")
|
||||
img:Dock(RIGHT)
|
||||
img:DockMargin(4, 4, 4, 4)
|
||||
img:InvalidateParent(true)
|
||||
img:SetWide(img:GetTall())
|
||||
img:SetImageColor(Color(52, 161, 224))
|
||||
img:SetImage("https://raw.githubusercontent.com/Srlion/Addons-Data/main/icons/sam/check_mark.png")
|
||||
|
||||
item.img = img
|
||||
end
|
||||
end
|
||||
|
||||
local limits_body
|
||||
|
||||
do
|
||||
local permissions_search = right_body:Add("SAM.TextEntry")
|
||||
permissions_search:Dock(TOP)
|
||||
permissions_search:DockMargin(0, 0, 5, 10)
|
||||
permissions_search:SetNoBar(true)
|
||||
permissions_search:SetPlaceholder("Search...")
|
||||
permissions_search:SetRadius(4)
|
||||
permissions_search:SetTall(30)
|
||||
|
||||
function permissions_search:OnValueChange(text)
|
||||
if limits_body and limits_body:IsVisible() then
|
||||
local children = limits_body:GetCanvas():GetChildren()
|
||||
for k, v in ipairs(children) do
|
||||
v:AnimatedSetVisible(v.title:find(text, nil, true) ~= nil)
|
||||
end
|
||||
limits_body:InvalidateLayout(true)
|
||||
else
|
||||
permissions_body:Search(text)
|
||||
end
|
||||
end
|
||||
|
||||
Line(right_body):SetZPos(2)
|
||||
end
|
||||
|
||||
local function load_limits()
|
||||
if sam.limit_types then
|
||||
if limits_body then return end
|
||||
else
|
||||
if limits_body then
|
||||
limits_body:SetVisible(false)
|
||||
permissions_body:AnimatedSetVisible(true)
|
||||
limits_body:Remove()
|
||||
limits_body = nil
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
limits_body = right_body:Add("SAM.ScrollPanel")
|
||||
limits_body:Dock(FILL)
|
||||
limits_body:GetCanvas():DockPadding(0, 0, 5, 0)
|
||||
limits_body:SetVisible(false)
|
||||
|
||||
local item_enter = function(s)
|
||||
if not IsValid(current_rank) then return end
|
||||
|
||||
local rank = current_rank.name
|
||||
|
||||
local limit = math.Clamp(s:GetValue(), -1, 1000)
|
||||
if limit ~= sam.ranks.get_limit(rank, s.limit_type) then
|
||||
RunConsoleCommand("sam", "changeranklimit", rank, s.limit_type, limit)
|
||||
else
|
||||
s:SetText(tostring(sam.ranks.get_limit(rank, s.limit_type)))
|
||||
end
|
||||
end
|
||||
|
||||
local not_empty = function(s)
|
||||
return s and s ~= ""
|
||||
end
|
||||
|
||||
local limit_values = {}
|
||||
for k, v in ipairs(sam.limit_types) do
|
||||
local immunity = limits_body:Add("SAM.LabelPanel")
|
||||
immunity:SetLabel(v)
|
||||
immunity:DockMargin(5, 0, 0, 5)
|
||||
|
||||
local entry = immunity:Add("SAM.TextEntry")
|
||||
entry:SetSize(60, 26)
|
||||
entry:SetNumeric(true)
|
||||
entry:DisallowFloats(true)
|
||||
entry:SetPlaceholder("")
|
||||
entry:SetCheck(not_empty)
|
||||
entry.limit_type = v
|
||||
entry.OnEnter = item_enter
|
||||
|
||||
table.insert(limit_values, entry)
|
||||
end
|
||||
|
||||
function limits_body:Refresh()
|
||||
if not IsValid(current_rank) then return end
|
||||
|
||||
local rank = current_rank.name
|
||||
for k, v in ipairs(limit_values) do
|
||||
v:SetValue(tostring(sam.ranks.get_limit(rank, v.limit_type)))
|
||||
end
|
||||
end
|
||||
|
||||
local right_current_rank = right_body:Add("SAM.Button")
|
||||
right_current_rank:Dock(BOTTOM)
|
||||
right_current_rank:DockMargin(0, 5, 0, 0)
|
||||
right_current_rank:SetFont(CREATE_RANK)
|
||||
right_current_rank:SetText("Switch to Limits")
|
||||
right_current_rank:On("DoClick", function()
|
||||
limits_body:AnimatedToggleVisible()
|
||||
permissions_body:AnimatedToggleVisible()
|
||||
|
||||
if permissions_body:AnimatedIsVisible() then
|
||||
right_current_rank:SetText("Switch to Limits")
|
||||
else
|
||||
right_current_rank:SetText("Switch to Permissions")
|
||||
end
|
||||
end)
|
||||
|
||||
limits_body:On("OnRemove", function()
|
||||
right_current_rank:Remove()
|
||||
end)
|
||||
limits_body:Refresh()
|
||||
end
|
||||
|
||||
local function refresh_all()
|
||||
timer.Create("SAM.Menu.Ranks.Refresh", 1, 1, function()
|
||||
load_limits()
|
||||
refresh_permissions()
|
||||
refresh_access()
|
||||
end)
|
||||
end
|
||||
|
||||
sam.config.hook({"Restrictions.Limits"}, refresh_all)
|
||||
|
||||
for k, v in ipairs({"SAM.AddedPermission", "SAM.PermissionModified", "SAM.RemovedPermission"}) do
|
||||
hook.Add(v, "SAM.Menu.RefreshPermissions", refresh_all)
|
||||
end
|
||||
|
||||
local body = parent:Add("SAM.ScrollPanel")
|
||||
body:Dock(FILL)
|
||||
body:DockMargin(10, 0, 5, 10)
|
||||
body:SetVBarPadding(6)
|
||||
|
||||
body:Line():SetZPos(-101)
|
||||
|
||||
local select_rank = function(s)
|
||||
if not IsValid(s) then
|
||||
current_rank = nil
|
||||
right_body:SizeTo(0, -1, 0.3)
|
||||
return
|
||||
end
|
||||
|
||||
if IsValid(current_rank) then
|
||||
current_rank.Selected = false
|
||||
|
||||
if current_rank == s then
|
||||
current_rank = nil
|
||||
right_body:SizeTo(0, -1, 0.3)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
s.Selected = true
|
||||
current_rank = s
|
||||
refresh_access()
|
||||
if limits_body then
|
||||
limits_body:Refresh()
|
||||
end
|
||||
right_body:SizeTo(SUI.Scale(300), -1, 0.3)
|
||||
|
||||
rank_title:SetText(s.name)
|
||||
rank_title:SizeToContents()
|
||||
end
|
||||
|
||||
local ranks = {}
|
||||
|
||||
function search_entry:OnValueChange()
|
||||
local value = self:GetValue()
|
||||
for k, v in pairs(ranks) do
|
||||
local show = k:find(value, nil, true)
|
||||
show = show ~= nil
|
||||
v.line:AnimatedSetVisible(show)
|
||||
v:GetParent():AnimatedSetVisible(show)
|
||||
end
|
||||
end
|
||||
|
||||
local add_rank = function(rank_name, data)
|
||||
if rank_name == "superadmin" then return end
|
||||
if not IsValid(body) then return end
|
||||
|
||||
local line = body:Add("SAM.Panel")
|
||||
line:Dock(TOP)
|
||||
line:DockMargin(0, 0, 0, 10)
|
||||
line:SetTall(34)
|
||||
line:SetZPos(-data.immunity)
|
||||
line:InvalidateLayout(true)
|
||||
|
||||
local container = line:Add("SAM.Button")
|
||||
container:Dock(FILL)
|
||||
container:DockMargin(0, 0, 5, 0)
|
||||
container:DockPadding(5, 5, 0, 5)
|
||||
container:SetText("")
|
||||
container:SetContained(false)
|
||||
container.name = rank_name
|
||||
|
||||
ranks[rank_name] = container
|
||||
|
||||
container:On("DoClick", select_rank)
|
||||
|
||||
function container:DoRightClick()
|
||||
rank_name = container.name
|
||||
|
||||
if rank_name == "user" then return end
|
||||
|
||||
local dmenu = vgui.Create("SAM.Menu")
|
||||
dmenu:SetSize(w, h)
|
||||
dmenu:SetInternal(container)
|
||||
|
||||
dmenu:AddOption("Edit Rank", function()
|
||||
rank_menu(rank_name, sam.ranks.get_rank(rank_name))
|
||||
end)
|
||||
|
||||
if not sam.ranks.is_default_rank(rank_name) then
|
||||
dmenu:AddSpacer()
|
||||
|
||||
dmenu:AddOption("Remove Rank", function()
|
||||
local remove_rank = vgui.Create("SAM.QueryBox")
|
||||
remove_rank:SetWide(350)
|
||||
|
||||
local check = remove_rank:Add("SAM.Label")
|
||||
check:SetText("Are you sure that you want to remove '" .. rank_name .. "'?")
|
||||
check:SetFont("SAMLine")
|
||||
check:SetWrap(true)
|
||||
check:SetAutoStretchVertical(true)
|
||||
|
||||
remove_rank:Done()
|
||||
remove_rank.save:SetEnabled(true)
|
||||
remove_rank.save:SetText("REMOVE")
|
||||
remove_rank.save:SetContained(false)
|
||||
remove_rank.save:SetColors(GetColor("query_box_cancel"), GetColor("query_box_cancel_text"))
|
||||
|
||||
remove_rank.cancel:SetContained(true)
|
||||
remove_rank.cancel:SetColors()
|
||||
|
||||
remove_rank:SetCallback(function()
|
||||
RunConsoleCommand("sam", "removerank", rank_name)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
dmenu:Open()
|
||||
dmenu:SetPos(input.GetCursorPos())
|
||||
end
|
||||
|
||||
do
|
||||
local name = container:Add("SAM.Label")
|
||||
name:Dock(TOP)
|
||||
name:DockMargin(0, 0, 0, 2)
|
||||
name:SetTextColor(GetColor("player_list_names"))
|
||||
name:SetFont(RANK_NAME)
|
||||
name:SetText(rank_name)
|
||||
name:SizeToContents()
|
||||
|
||||
local immunity = container:Add("SAM.Label")
|
||||
immunity:Dock(TOP)
|
||||
immunity:SetTextColor(GetColor("player_list_steamid"))
|
||||
immunity:SetFont(RANK_INFO)
|
||||
immunity:SetText("Immunity: " .. data.immunity)
|
||||
immunity:SizeToContents()
|
||||
|
||||
local banlimit = container:Add("SAM.Label")
|
||||
banlimit:Dock(TOP)
|
||||
banlimit:SetTextColor(GetColor("player_list_steamid"))
|
||||
banlimit:SetFont(RANK_INFO)
|
||||
banlimit:SetText("Ban limit: " .. sam.reverse_parse_length(sam.parse_length(data.ban_limit)))
|
||||
banlimit:SizeToContents()
|
||||
|
||||
local inherit = container:Add("SAM.Label")
|
||||
inherit:Dock(TOP)
|
||||
inherit:SetTextColor(GetColor("player_list_steamid"))
|
||||
inherit:SetFont(RANK_INFO)
|
||||
inherit:SetText("Inherits from: " .. (sam.isstring(data.inherit) and data.inherit or "none"))
|
||||
inherit:SizeToContents()
|
||||
end
|
||||
|
||||
container:InvalidateLayout(true)
|
||||
container:SizeToChildren(false, true)
|
||||
line:SizeToChildren(false, true)
|
||||
|
||||
local _line = body:Line()
|
||||
_line:SetZPos(-data.immunity)
|
||||
|
||||
container.line = _line
|
||||
container.data = data
|
||||
end
|
||||
|
||||
for rank_name, v in pairs(sam.ranks.get_ranks()) do
|
||||
add_rank(rank_name, v)
|
||||
end
|
||||
|
||||
hook.Add("SAM.AddedRank", "SAM.RefreshRanksList", function(name, rank)
|
||||
add_rank(name, rank)
|
||||
end)
|
||||
|
||||
hook.Add("SAM.RemovedRank", "SAM.RefreshRanksList", function(name)
|
||||
local line = ranks[name]
|
||||
if not IsValid(line) then return end
|
||||
|
||||
line.line:Remove()
|
||||
line:GetParent():Remove()
|
||||
ranks[name] = nil
|
||||
|
||||
if line == current_rank then
|
||||
select_rank()
|
||||
end
|
||||
end)
|
||||
|
||||
-- This is just better than caching panels for stuff that ain't gonna be called a lot
|
||||
hook.Add("SAM.RankNameChanged", "SAM.RefreshRanksList", function(name, new_name)
|
||||
local line = ranks[name]
|
||||
if not IsValid(line) then return end
|
||||
|
||||
-- if current_rank == name then
|
||||
-- rank_name:SetText(new_name)
|
||||
-- end
|
||||
|
||||
line:GetChildren()[1]:SetText(new_name)
|
||||
|
||||
ranks[new_name], ranks[name] = line, nil
|
||||
line.name = new_name
|
||||
end)
|
||||
|
||||
hook.Add("SAM.RankImmunityChanged", "SAM.RefreshRanksList", function(name, immunity)
|
||||
local line = ranks[name]
|
||||
if not IsValid(line) then return end
|
||||
|
||||
line:GetChildren()[2]:SetText("Immunity: " .. immunity)
|
||||
line:GetParent():SetZPos(-immunity)
|
||||
|
||||
-- SetZPos is kinda weird to deal with
|
||||
line.line:SetZPos(-immunity + 1)
|
||||
line.line:SetZPos(-immunity)
|
||||
end)
|
||||
|
||||
hook.Add("SAM.RankBanLimitChanged", "SAM.RefreshRanksList", function(name, new_limit)
|
||||
local line = ranks[name]
|
||||
if IsValid(line) then
|
||||
line:GetChildren()[3]:SetText("Ban limit: " .. sam.reverse_parse_length(new_limit))
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("SAM.ChangedInheritRank", "SAM.RefreshRanksList", function(name, new_inherit)
|
||||
local line = ranks[name]
|
||||
if IsValid(line) then
|
||||
line:GetChildren()[4]:SetText("Inherits from: " .. new_inherit)
|
||||
end
|
||||
end)
|
||||
|
||||
return parent
|
||||
end, function()
|
||||
return LocalPlayer():HasPermission("manage_ranks")
|
||||
end, 3)
|
||||
Reference in New Issue
Block a user