mirror of
https://github.com/gmod-integration/lua.git
synced 2025-03-15 22:27:34 +00:00
commit
2b09ea91c9
|
@ -1,66 +1,67 @@
|
|||
if game.SinglePlayer() then return end
|
||||
if (game.SinglePlayer()) then return print("Gmod Integration is not supported in Singleplayer!") end
|
||||
|
||||
//
|
||||
// Variables
|
||||
//
|
||||
|
||||
gmInte = gmInte or {}
|
||||
gmInte.version = "0.2.3"
|
||||
gmInte.config = {
|
||||
["redownloadMaterials"] = false,
|
||||
}
|
||||
gmInte = gmInte || {}
|
||||
|
||||
gmInte.version = "0.3.0"
|
||||
gmInte.config = {}
|
||||
gmInte.materials = {}
|
||||
|
||||
//
|
||||
// Functions
|
||||
//
|
||||
|
||||
local function loadConfig()
|
||||
if (SERVER) then
|
||||
print(" | Loading File | gmod_integration/sv_config.lua")
|
||||
RunConsoleCommand("sv_hibernate_think", "1")
|
||||
if (!file.Exists("gm_integration", "DATA") || !file.Exists("gm_integration/config.json", "DATA")) then
|
||||
file.CreateDir("gm_integration")
|
||||
local function loadServerConfig()
|
||||
RunConsoleCommand("sv_hibernate_think", "1")
|
||||
|
||||
if (!file.Exists("gm_integration", "DATA") || !file.Exists("gm_integration/config.json", "DATA")) then
|
||||
file.CreateDir("gm_integration")
|
||||
file.Write("gm_integration/config.json", util.TableToJSON(gmInte.config, true))
|
||||
else
|
||||
if (gmInte.config.id && gmInte.config.id != "") then return end
|
||||
|
||||
local oldConfig = util.JSONToTable(file.Read("gm_integration/config.json", "DATA"))
|
||||
if (!oldConfig.version || (oldConfig.version < gmInte.version)) then
|
||||
print(" | Merging Config | gmod_integration/sv_config.lua")
|
||||
table.Merge(gmInte.config, oldConfig)
|
||||
gmInte.config.version = gmInte.version
|
||||
file.Write("gm_integration/config.json", util.TableToJSON(gmInte.config, true))
|
||||
else
|
||||
if (gmInte.config.id && gmInte.config.id != "") then return end
|
||||
|
||||
local oldConfig = util.JSONToTable(file.Read("gm_integration/config.json", "DATA"))
|
||||
if (!oldConfig.version || (oldConfig.version < gmInte.version)) then
|
||||
print(" | Merging Config | gmod_integration/sv_config.lua")
|
||||
table.Merge(gmInte.config, oldConfig)
|
||||
gmInte.config.version = gmInte.version
|
||||
file.Write("gm_integration/config.json", util.TableToJSON(gmInte.config, true))
|
||||
else
|
||||
gmInte.config = oldConfig
|
||||
end
|
||||
gmInte.config = oldConfig
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function loadAllFiles(folder)
|
||||
local files, folders = file.Find(folder .. "/*", "LUA")
|
||||
for k, v in SortedPairs(files) do
|
||||
local path = folder .. "/" .. v
|
||||
|
||||
for k, fileName in SortedPairs(files) do
|
||||
local path = folder .. "/" .. fileName
|
||||
print(" | Loading File | " .. path)
|
||||
if string.StartWith(v, "cl_") then
|
||||
|
||||
if (string.StartWith(fileName, "cl_")) then
|
||||
if SERVER then
|
||||
AddCSLuaFile(path)
|
||||
else
|
||||
include(path)
|
||||
end
|
||||
elseif string.StartWith(v, "sv_") then
|
||||
elseif (string.StartWith(fileName, "sv_")) then
|
||||
if SERVER then
|
||||
include(path)
|
||||
end
|
||||
elseif string.StartWith(v, "sh_") then
|
||||
elseif (string.StartWith(fileName, "sh_")) then
|
||||
if SERVER then
|
||||
AddCSLuaFile(path)
|
||||
end
|
||||
include(path)
|
||||
end
|
||||
if (path == "gmod_integration/sv_config.lua") then loadConfig() continue end
|
||||
|
||||
if (fileName == "sv_config.lua") then loadServerConfig() continue end
|
||||
end
|
||||
|
||||
for k, v in SortedPairs(folders, true) do
|
||||
loadAllFiles(folder .. "/" .. v, name)
|
||||
end
|
||||
|
|
23
lua/gmod_integration/client/cl__color.lua
Normal file
23
lua/gmod_integration/client/cl__color.lua
Normal file
|
@ -0,0 +1,23 @@
|
|||
local colorTbl = {
|
||||
["background"] = Color(41, 44, 54),
|
||||
["primary"] = Color(58, 62, 73),
|
||||
["primary-active"] = Color(58, 62, 73, 163),
|
||||
["secondary"] = Color(44, 47, 59),
|
||||
["secondary-active"] = Color(31, 33, 40),
|
||||
["green"] = Color(78, 151, 53),
|
||||
["green-active"] = Color(58, 122, 38),
|
||||
["orange"] = Color(204, 145, 62),
|
||||
["orange-active"] = Color(168, 122, 43),
|
||||
["red"] = Color(201, 59, 59),
|
||||
["red-active"] = Color(168, 43, 43),
|
||||
["blue"] = Color(67, 197, 214),
|
||||
["blue-active"] = Color(41, 152, 167),
|
||||
["purple"] = Color(73, 90, 252),
|
||||
["purple-active"] = Color(47, 63, 159),
|
||||
["font"] = Color(255, 255, 255),
|
||||
["font-secondary"] = Color(179, 179, 179)
|
||||
}
|
||||
|
||||
function gmInte.getColor(name)
|
||||
return colorTbl[name]
|
||||
end
|
12
lua/gmod_integration/client/cl_context_menu.lua
Normal file
12
lua/gmod_integration/client/cl_context_menu.lua
Normal file
|
@ -0,0 +1,12 @@
|
|||
list.Set("DesktopWindows", "GmodIntegration:DesktopWindows", {
|
||||
icon = "gmod_integration/logo_context.png",
|
||||
title = "GM Integration",
|
||||
width = 960,
|
||||
height = 700,
|
||||
onewindow = true,
|
||||
init = function(icon, window)
|
||||
window:Close()
|
||||
gmInte.openAdminConfig()
|
||||
end
|
||||
}
|
||||
)
|
|
@ -1,7 +1,7 @@
|
|||
surface.CreateFont("GmodIntegration_Roboto_16", {
|
||||
font = "Roboto",
|
||||
size = 16,
|
||||
weight = 500,
|
||||
weight = 100,
|
||||
antialias = true,
|
||||
shadow = false
|
||||
})
|
||||
|
|
|
@ -1,436 +0,0 @@
|
|||
local function saveConfig(setting, value)
|
||||
gmInte.SendNet(3, {
|
||||
[setting] = value
|
||||
})
|
||||
end
|
||||
|
||||
local configCat = {
|
||||
"Authentication",
|
||||
"Main",
|
||||
"Trust & Safety",
|
||||
"Punishment",
|
||||
"Other"
|
||||
}
|
||||
|
||||
local possibleConfig = {
|
||||
["id"] = {
|
||||
["label"] = "ID",
|
||||
["description"] = "Server ID found on the webpanel.",
|
||||
["type"] = "textEntry",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value)
|
||||
end,
|
||||
["onEditDelay"] = 0.5,
|
||||
["category"] = "Authentication"
|
||||
},
|
||||
["token"] = {
|
||||
["label"] = "Token",
|
||||
["description"] = "Server Token found on the webpanel.",
|
||||
["type"] = "textEntry",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value)
|
||||
end,
|
||||
["onEditDelay"] = 0.5,
|
||||
["category"] = "Authentication"
|
||||
},
|
||||
["sendLog"] = {
|
||||
["label"] = "Logs",
|
||||
["description"] = "Activate or deactivate logs.",
|
||||
["type"] = "checkbox",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value == "Enabled" && true || false)
|
||||
end,
|
||||
["category"] = "Main"
|
||||
},
|
||||
["logBotActions"] = {
|
||||
["label"] = "Log Bot Actions",
|
||||
["description"] = "Activate or deactivate logs for bot actions.",
|
||||
["type"] = "checkbox",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value == "Enabled" && true || false)
|
||||
end,
|
||||
["category"] = "Main"
|
||||
},
|
||||
["filterOnBan"] = {
|
||||
["label"] = "Block Discord Ban Player",
|
||||
["description"] = "Block players banned on the discord server.",
|
||||
["type"] = "checkbox",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value == "Enabled" && true || false)
|
||||
end,
|
||||
["category"] = "Trust & Safety"
|
||||
},
|
||||
["filterOnTrust"] = {
|
||||
["label"] = "Block UnTrust Player",
|
||||
["description"] = "Block players with a trust level lower than the minimal trust level set in the config.",
|
||||
["type"] = "checkbox",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value == "Enabled" && true || false)
|
||||
end,
|
||||
["category"] = "Trust & Safety"
|
||||
},
|
||||
["minimalTrust"] = {
|
||||
["label"] = "Minimal Trust Level",
|
||||
["description"] = "The minimal trust level to be able to join the server.",
|
||||
["type"] = "textEntry",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value)
|
||||
end,
|
||||
["onEditDelay"] = 0.5,
|
||||
["category"] = "Trust & Safety"
|
||||
},
|
||||
["syncChat"] = {
|
||||
["label"] = "Sync Chat",
|
||||
["description"] = "Sync chat between the server and the discord server.",
|
||||
["websocket"] = true,
|
||||
["restart"] = true,
|
||||
["type"] = "checkbox",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value == "Enabled" && true || false)
|
||||
end,
|
||||
["category"] = "Main"
|
||||
},
|
||||
["syncBan"] = {
|
||||
["label"] = "Sync Ban",
|
||||
["description"] = "Sync chat between the server and the discord server.",
|
||||
["type"] = "checkbox",
|
||||
["disable"] = true,
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value == "Enabled" && true || false)
|
||||
end,
|
||||
["category"] = "Punishment"
|
||||
},
|
||||
["syncTimeout"] = {
|
||||
["label"] = "Sync Timeout",
|
||||
["description"] = "Sync chat between the server and the discord server.",
|
||||
["type"] = "checkbox",
|
||||
["disable"] = true,
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value == "Enabled" && true || false)
|
||||
end,
|
||||
["category"] = "Punishment"
|
||||
},
|
||||
["syncKick"] = {
|
||||
["label"] = "Sync Kick",
|
||||
["description"] = "Sync chat between the server and the discord server.",
|
||||
["type"] = "checkbox",
|
||||
["disable"] = true,
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value == "Enabled" && true || false)
|
||||
end,
|
||||
["category"] = "Punishment"
|
||||
},
|
||||
["forcePlayerLink"] = {
|
||||
["label"] = "Force Player Verif",
|
||||
["description"] = "Sync chat between the server and the discord server.",
|
||||
["type"] = "checkbox",
|
||||
["disable"] = true,
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value == "Enabled" && true || false)
|
||||
end,
|
||||
["category"] = "Main"
|
||||
},
|
||||
["supportLink"] = {
|
||||
["label"] = "Support Link",
|
||||
["description"] = "Server ID found on the webpanel.",
|
||||
["type"] = "textEntry",
|
||||
["disable"] = true,
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value)
|
||||
end,
|
||||
["onEditDelay"] = 0.5,
|
||||
["category"] = "Trust & Safety"
|
||||
},
|
||||
["debug"] = {
|
||||
["label"] = "Debug",
|
||||
["description"] = "Activate or deactivate debug mode.",
|
||||
["type"] = "checkbox",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value == "Enabled" && true || false)
|
||||
end,
|
||||
["category"] = "Other"
|
||||
},
|
||||
['devInstance'] = {
|
||||
["label"] = "Dev Instance",
|
||||
["description"] = "Activate or deactivate the dev instance of the API and Websocket.",
|
||||
["type"] = "checkbox",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value == "Enabled" && true || false)
|
||||
end,
|
||||
["category"] = "Other"
|
||||
}
|
||||
}
|
||||
|
||||
local buttonsInfo = {
|
||||
{
|
||||
["label"] = "Open Webpanel",
|
||||
["func"] = function()
|
||||
gui.OpenURL("https://gmod-integration.com/config/server")
|
||||
end,
|
||||
},
|
||||
{
|
||||
["label"] = "Test Connection",
|
||||
["func"] = function()
|
||||
gmInte.SendNet(1)
|
||||
end,
|
||||
},
|
||||
{
|
||||
["label"] = "Buy Premium",
|
||||
["func"] = function()
|
||||
gui.OpenURL("https://gmod-integration.com/premium")
|
||||
end,
|
||||
},
|
||||
{
|
||||
["label"] = "Install Websocket",
|
||||
["condition"] = function(data)
|
||||
return !data.websocket
|
||||
end,
|
||||
["func"] = function()
|
||||
gui.OpenURL("https://github.com/FredyH/GWSockets/releases")
|
||||
end,
|
||||
},
|
||||
{
|
||||
["label"] = "Load Server Config",
|
||||
["condition"] = function(data)
|
||||
return data.debug
|
||||
end,
|
||||
["func"] = function(data)
|
||||
gmInte.config = data
|
||||
end,
|
||||
}
|
||||
}
|
||||
|
||||
function gmInte.needRestart()
|
||||
local frame = vgui.Create("DFrame")
|
||||
frame:SetSize(400, 120)
|
||||
frame:Center()
|
||||
frame:SetTitle("Gmod Integration - Restart Required")
|
||||
frame:SetDraggable(true)
|
||||
frame:ShowCloseButton(true)
|
||||
frame:MakePopup()
|
||||
|
||||
local messagePanel = vgui.Create("DPanel", frame)
|
||||
messagePanel:Dock(TOP)
|
||||
messagePanel:SetSize(300, 40)
|
||||
messagePanel:DockMargin(10, 0, 10, 10)
|
||||
messagePanel:SetBackgroundColor(Color(0, 0, 0, 0))
|
||||
|
||||
local messageLabel = vgui.Create("DLabel", messagePanel)
|
||||
messageLabel:Dock(FILL)
|
||||
messageLabel:SetText("Some changes require a restart to be applied.\nRestart now ?")
|
||||
messageLabel:SetContentAlignment(5)
|
||||
messageLabel:SetWrap(true)
|
||||
|
||||
local buttonGrid = vgui.Create("DGrid", frame)
|
||||
buttonGrid:Dock(BOTTOM)
|
||||
buttonGrid:DockMargin(5, 10, 5, 5)
|
||||
buttonGrid:SetCols(2)
|
||||
buttonGrid:SetColWide(frame:GetWide() / 2 - 10)
|
||||
buttonGrid:SetRowHeight(35)
|
||||
|
||||
local button = vgui.Create("DButton")
|
||||
button:SetText("Restart")
|
||||
button.DoClick = function()
|
||||
frame:Close()
|
||||
gmInte.SendNet(5)
|
||||
end
|
||||
button:SetSize(buttonGrid:GetColWide(), buttonGrid:GetRowHeight())
|
||||
buttonGrid:AddItem(button)
|
||||
|
||||
local button = vgui.Create("DButton")
|
||||
button:SetText("Maybe Later")
|
||||
button.DoClick = function()
|
||||
frame:Close()
|
||||
end
|
||||
button:SetSize(buttonGrid:GetColWide(), buttonGrid:GetRowHeight())
|
||||
buttonGrid:AddItem(button)
|
||||
end
|
||||
|
||||
function gmInte.openConfigMenu(data)
|
||||
local needRestart = false
|
||||
|
||||
local frame = vgui.Create("DFrame")
|
||||
frame:SetSize(400, (600 / 1080) * ScrH())
|
||||
frame:Center()
|
||||
frame:SetTitle("Gmod Integration - Server Config")
|
||||
frame:SetDraggable(true)
|
||||
frame:ShowCloseButton(true)
|
||||
frame:MakePopup()
|
||||
|
||||
local scrollPanel = vgui.Create("DScrollPanel", frame)
|
||||
scrollPanel:Dock(FILL)
|
||||
|
||||
local messagePanel = vgui.Create("DPanel", scrollPanel)
|
||||
messagePanel:Dock(TOP)
|
||||
messagePanel:SetSize(300, 60)
|
||||
messagePanel:DockMargin(10, 0, 10, 10)
|
||||
messagePanel:SetBackgroundColor(Color(0, 0, 0, 0))
|
||||
|
||||
local messageLabel = vgui.Create("DLabel", messagePanel)
|
||||
messageLabel:Dock(FILL)
|
||||
messageLabel:SetText("This config is superior to the webpanel config.\nIf you change something here you can override the webpanel config.\nSome features require a websocket connection to work properly.")
|
||||
messageLabel:SetWrap(true)
|
||||
|
||||
for k, catName in pairs(configCat) do
|
||||
local collapsibleCategory = vgui.Create("DCollapsibleCategory", scrollPanel)
|
||||
collapsibleCategory:Dock(TOP)
|
||||
collapsibleCategory:DockMargin(10, 0, 10, 10)
|
||||
collapsibleCategory:SetLabel(catName)
|
||||
collapsibleCategory:SetExpanded(true)
|
||||
|
||||
local configList = vgui.Create("DPanelList", collapsibleCategory)
|
||||
configList:Dock(FILL)
|
||||
configList:SetSpacing(5)
|
||||
configList:EnableHorizontal(false)
|
||||
configList:EnableVerticalScrollbar(false)
|
||||
collapsibleCategory:SetContents(configList)
|
||||
|
||||
for k, v in pairs(possibleConfig) do
|
||||
if v.category == catName then
|
||||
local panel = vgui.Create("DPanel", configList)
|
||||
panel:Dock(TOP)
|
||||
panel:SetSize(300, 25)
|
||||
panel:SetBackgroundColor(Color(0, 0, 0, 0))
|
||||
|
||||
local label = vgui.Create("DLabel", panel)
|
||||
label:Dock(LEFT)
|
||||
label:SetSize(140, 25)
|
||||
label:SetText(v.label)
|
||||
label:SetContentAlignment(4)
|
||||
|
||||
local input
|
||||
|
||||
if v.type == "textEntry" then
|
||||
input = vgui.Create("DTextEntry", panel)
|
||||
input:SetText(v.value(k, data[k]))
|
||||
local isLastID = 0
|
||||
input.OnChange = function(self)
|
||||
isLastID = isLastID + 1
|
||||
local isLocalLastID = isLastID
|
||||
timer.Simple(v.onEditDelay || 0.5, function()
|
||||
if isLocalLastID == isLastID then
|
||||
v.onEdit(k, self:GetValue())
|
||||
end
|
||||
end)
|
||||
end
|
||||
elseif (v.type == "checkbox") then
|
||||
input = vgui.Create("DComboBox", panel)
|
||||
if (v.disable) then
|
||||
input:SetEnabled(false)
|
||||
end
|
||||
input:AddChoice("Enabled")
|
||||
input:AddChoice("Disabled")
|
||||
input:SetText(v.value(k, data[k]) && "Enabled" || "Disabled")
|
||||
input.OnSelect = function(self, index, value)
|
||||
if (v.restart) then
|
||||
needRestart = true
|
||||
end
|
||||
v.onEdit(k, value)
|
||||
end
|
||||
end
|
||||
|
||||
input:Dock(FILL)
|
||||
input:SetSize(150, 25)
|
||||
|
||||
if (v.description) then
|
||||
if (v.websocket && !data.websocket) then
|
||||
v.description = v.description .. "\n\nThis feature require a websocket connection to work properly."
|
||||
end
|
||||
if (v.disable) then
|
||||
v.description = v.description .. "\n\nThis feature will be available soon."
|
||||
end
|
||||
input:SetTooltip(v.description)
|
||||
end
|
||||
|
||||
configList:AddItem(panel)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local buttonGrid = vgui.Create("DGrid", frame)
|
||||
buttonGrid:Dock(BOTTOM)
|
||||
buttonGrid:DockMargin(5, 10, 5, 5)
|
||||
buttonGrid:SetCols(2)
|
||||
buttonGrid:SetColWide(frame:GetWide() / 2 - 10)
|
||||
buttonGrid:SetRowHeight(35)
|
||||
|
||||
local buttonsCount = 0
|
||||
for k, v in pairs(buttonsInfo) do
|
||||
if (v.condition && !v.condition(data)) then continue end
|
||||
local button = vgui.Create("DButton")
|
||||
button:SetText(v.label)
|
||||
button.DoClick = function()
|
||||
v.func(data)
|
||||
end
|
||||
button:SetSize(buttonGrid:GetColWide(), buttonGrid:GetRowHeight())
|
||||
buttonGrid:AddItem(button)
|
||||
buttonsCount = buttonsCount + 1
|
||||
end
|
||||
|
||||
if (buttonsCount % 2 == 1) then
|
||||
local lastButton = buttonGrid:GetItems()[buttonsCount]
|
||||
lastButton:SetWide(frame:GetWide() - 20)
|
||||
end
|
||||
|
||||
frame.OnClose = function()
|
||||
if (needRestart) then gmInte.needRestart() end
|
||||
end
|
||||
end
|
||||
|
||||
list.Set("DesktopWindows", "GmodIntegration:DesktopWindows", {
|
||||
icon = "gmod_integration/logo_context.png",
|
||||
title = "GM Integration",
|
||||
width = 960,
|
||||
height = 700,
|
||||
onewindow = true,
|
||||
init = function(icon, window)
|
||||
window:Close()
|
||||
gmInte.openAdminConfig()
|
||||
end
|
||||
}
|
||||
)
|
490
lua/gmod_integration/client/cl_gui_admin.lua
Normal file
490
lua/gmod_integration/client/cl_gui_admin.lua
Normal file
|
@ -0,0 +1,490 @@
|
|||
local function saveConfig(setting, value)
|
||||
gmInte.SendNet("saveConfig", {
|
||||
[setting] = value
|
||||
})
|
||||
end
|
||||
|
||||
local configCat = {
|
||||
"Authentication",
|
||||
"Main",
|
||||
"Trust & Safety",
|
||||
-- "Punishment",
|
||||
"Advanced",
|
||||
}
|
||||
|
||||
local possibleConfig = {
|
||||
{
|
||||
["id"] = "id",
|
||||
["label"] = "Server ID",
|
||||
["description"] = "Server ID found on the webpanel.",
|
||||
["type"] = "textEntry",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value)
|
||||
end,
|
||||
["onEditDelay"] = 0.5,
|
||||
["category"] = "Authentication"
|
||||
},
|
||||
{
|
||||
["id"]= "token",
|
||||
["label"] = "Server Token",
|
||||
["description"] = "Server Token found on the webpanel.",
|
||||
["type"] = "textEntry",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value)
|
||||
end,
|
||||
["onEditDelay"] = 0.5,
|
||||
["category"] = "Authentication"
|
||||
},
|
||||
-- {
|
||||
-- ["id"]= "sendLog",
|
||||
-- ["label"] = "Logs",
|
||||
-- ["description"] = "Activate or deactivate logs.",
|
||||
-- ["type"] = "checkbox",
|
||||
-- ["value"] = function(setting, value)
|
||||
-- return value
|
||||
-- end,
|
||||
-- ["onEdit"] = function(setting, value)
|
||||
-- saveConfig(setting, value == "Enabled" && true || false)
|
||||
-- end,
|
||||
-- ["category"] = "Main"
|
||||
-- },
|
||||
-- {
|
||||
-- ["id"]= "logBotActions",
|
||||
-- ["label"] = "Log Bot Actions",
|
||||
-- ["description"] = "Activate or deactivate logs for bot actions.",
|
||||
-- ["type"] = "checkbox",
|
||||
-- ["value"] = function(setting, value)
|
||||
-- return value
|
||||
-- end,
|
||||
-- ["onEdit"] = function(setting, value)
|
||||
-- saveConfig(setting, value == "Enabled" && true || false)
|
||||
-- end,
|
||||
-- ["category"] = "Main"
|
||||
-- },
|
||||
{
|
||||
["id"]= "maintenance",
|
||||
["label"] = "Maintenance",
|
||||
["description"] = "Activate or deactivate maintenance mode.",
|
||||
["type"] = "checkbox",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value == "Enabled" && true || false)
|
||||
end,
|
||||
["category"] = "Main"
|
||||
},
|
||||
{
|
||||
["id"]= "filterOnBan",
|
||||
["label"] = "Block Discord Ban Player",
|
||||
["description"] = "Block players banned on the discord server.",
|
||||
["type"] = "checkbox",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value == "Enabled" && true || false)
|
||||
end,
|
||||
["category"] = "Trust & Safety"
|
||||
},
|
||||
-- {
|
||||
-- ["id"]= "filterOnTrust",
|
||||
-- ["label"] = "Block UnTrust Player",
|
||||
-- ["description"] = "Block players with a trust level lower than the minimal trust level set in the config.",
|
||||
-- ["type"] = "checkbox",
|
||||
-- ["value"] = function(setting, value)
|
||||
-- return value
|
||||
-- end,
|
||||
-- ["onEdit"] = function(setting, value)
|
||||
-- saveConfig(setting, value == "Enabled" && true || false)
|
||||
-- end,
|
||||
-- ["category"] = "Trust & Safety"
|
||||
-- },
|
||||
-- {
|
||||
-- ["id"]= "minimalTrust",
|
||||
-- ["label"] = "Minimal Trust Level",
|
||||
-- ["description"] = "The minimal trust level to be able to join the server.",
|
||||
-- ["type"] = "textEntry",
|
||||
-- ["value"] = function(setting, value)
|
||||
-- return value
|
||||
-- end,
|
||||
-- ["onEdit"] = function(setting, value)
|
||||
-- saveConfig(setting, value)
|
||||
-- end,
|
||||
-- ["onEditDelay"] = 0.5,
|
||||
-- ["category"] = "Trust & Safety"
|
||||
-- },
|
||||
-- {
|
||||
-- ["id"]= "syncChat",
|
||||
-- ["label"] = "Sync Chat",
|
||||
-- ["description"] = "Sync chat between the server and the discord server.",
|
||||
-- ["websocket"] = true,
|
||||
-- ["restart"] = true,
|
||||
-- ["type"] = "checkbox",
|
||||
-- ["value"] = function(setting, value)
|
||||
-- return value
|
||||
-- end,
|
||||
-- ["onEdit"] = function(setting, value)
|
||||
-- saveConfig(setting, value == "Enabled" && true || false)
|
||||
-- end,
|
||||
-- ["category"] = "Main"
|
||||
-- },
|
||||
-- {
|
||||
-- ["id"]= "syncBan",
|
||||
-- ["label"] = "Sync Ban",
|
||||
-- ["description"] = "Sync chat between the server and the discord server.",
|
||||
-- ["type"] = "checkbox",
|
||||
-- ["condition"] = function(data)
|
||||
-- return false // Disabled for now
|
||||
-- end,
|
||||
-- ["value"] = function(setting, value)
|
||||
-- return value
|
||||
-- end,
|
||||
-- ["onEdit"] = function(setting, value)
|
||||
-- saveConfig(setting, value == "Enabled" && true || false)
|
||||
-- end,
|
||||
-- ["category"] = "Punishment"
|
||||
-- },
|
||||
-- {
|
||||
-- ["id"]= "syncTimeout",
|
||||
-- ["label"] = "Sync Timeout",
|
||||
-- ["description"] = "Sync chat between the server and the discord server.",
|
||||
-- ["type"] = "checkbox",
|
||||
-- ["condition"] = function(data)
|
||||
-- return false // Disabled for now
|
||||
-- end,
|
||||
-- ["value"] = function(setting, value)
|
||||
-- return value
|
||||
-- end,
|
||||
-- ["onEdit"] = function(setting, value)
|
||||
-- saveConfig(setting, value == "Enabled" && true || false)
|
||||
-- end,
|
||||
-- ["category"] = "Punishment"
|
||||
-- },
|
||||
-- {
|
||||
-- ["id"]= "syncKick",
|
||||
-- ["label"] = "Sync Kick",
|
||||
-- ["description"] = "Sync chat between the server and the discord server.",
|
||||
-- ["type"] = "checkbox",
|
||||
-- ["condition"] = function(data)
|
||||
-- return false // Disabled for now
|
||||
-- end,
|
||||
-- ["value"] = function(setting, value)
|
||||
-- return value
|
||||
-- end,
|
||||
-- ["onEdit"] = function(setting, value)
|
||||
-- saveConfig(setting, value == "Enabled" && true || false)
|
||||
-- end,
|
||||
-- ["category"] = "Punishment"
|
||||
-- },
|
||||
{
|
||||
["id"]= "forcePlayerLink",
|
||||
["label"] = "Force Player Verif",
|
||||
["description"] = "Sync chat between the server and the discord server.",
|
||||
["type"] = "checkbox",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value == "Enabled" && true || false)
|
||||
end,
|
||||
["category"] = "Main"
|
||||
},
|
||||
{
|
||||
["id"]= "supportLink",
|
||||
["label"] = "Support Link",
|
||||
["description"] = "Server ID found on the webpanel.",
|
||||
["type"] = "textEntry",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value)
|
||||
end,
|
||||
["onEditDelay"] = 0.5,
|
||||
["category"] = "Trust & Safety"
|
||||
},
|
||||
{
|
||||
["id"]= "debug",
|
||||
["label"] = "Debug",
|
||||
["description"] = "Activate or deactivate debug mode.",
|
||||
["type"] = "checkbox",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["position"] = 1,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value == "Enabled" && true || false)
|
||||
end,
|
||||
["category"] = "Advanced"
|
||||
},
|
||||
{
|
||||
["id"]= "websocketFQDN",
|
||||
["label"] = "Websocket FQDN",
|
||||
["description"] = "Websocket FQDN that will be used for the Websocket connection.",
|
||||
["type"] = "textEntry",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value)
|
||||
end,
|
||||
["onEditDelay"] = 0.5,
|
||||
["category"] = "Advanced"
|
||||
},
|
||||
{
|
||||
["id"]= "apiFQDN",
|
||||
["label"] = "API FQDN",
|
||||
["description"] = "API FQDN that will be used for the API connection.",
|
||||
["type"] = "textEntry",
|
||||
["value"] = function(setting, value)
|
||||
return value
|
||||
end,
|
||||
["onEdit"] = function(setting, value)
|
||||
saveConfig(setting, value)
|
||||
end,
|
||||
["onEditDelay"] = 0.5,
|
||||
["category"] = "Advanced"
|
||||
},
|
||||
}
|
||||
|
||||
local buttonsInfo = {
|
||||
{
|
||||
["label"] = "Open Webpanel",
|
||||
["func"] = function()
|
||||
gui.OpenURL("https://gmod-integration.com/config/server")
|
||||
end,
|
||||
},
|
||||
{
|
||||
["label"] = "Test Connection",
|
||||
["func"] = function()
|
||||
gmInte.SendNet("testConnection")
|
||||
end,
|
||||
},
|
||||
{
|
||||
["label"] = "Buy Premium",
|
||||
["func"] = function()
|
||||
gui.OpenURL("https://gmod-integration.com/premium")
|
||||
end,
|
||||
},
|
||||
{
|
||||
["label"] = "Install Websocket",
|
||||
["condition"] = function(data)
|
||||
return !data.websocket
|
||||
end,
|
||||
["func"] = function()
|
||||
gui.OpenURL("https://github.com/FredyH/GWSockets/releases")
|
||||
end,
|
||||
},
|
||||
{
|
||||
["label"] = "Load Server Config",
|
||||
["condition"] = function(data)
|
||||
return data.debug
|
||||
end,
|
||||
["func"] = function(data)
|
||||
gmInte.config = data
|
||||
end,
|
||||
}
|
||||
}
|
||||
|
||||
local colorTable = {
|
||||
["text"] = Color(255, 255, 255, 255),
|
||||
["background"] = Color(0, 0, 0, 200),
|
||||
["button"] = Color(0, 0, 0, 200),
|
||||
["buttonHover"] = Color(0, 0, 0, 255),
|
||||
["buttonText"] = Color(255, 255, 255, 255),
|
||||
["buttonTextHover"] = Color(255, 255, 255, 255),
|
||||
}
|
||||
|
||||
function gmInte.needRestart()
|
||||
local frame = vgui.Create("DFrame")
|
||||
frame:SetSize(400, 120)
|
||||
frame:Center()
|
||||
frame:SetTitle("Gmod Integration - Restart Required")
|
||||
frame:SetDraggable(true)
|
||||
frame:ShowCloseButton(true)
|
||||
frame:MakePopup()
|
||||
|
||||
local messagePanel = vgui.Create("DPanel", frame)
|
||||
messagePanel:Dock(TOP)
|
||||
messagePanel:SetSize(300, 40)
|
||||
messagePanel:DockMargin(10, 0, 10, 10)
|
||||
messagePanel:SetBackgroundColor(Color(0, 0, 0, 0))
|
||||
|
||||
local messageLabel = vgui.Create("DLabel", messagePanel)
|
||||
messageLabel:Dock(FILL)
|
||||
messageLabel:SetText("Some changes require a restart to be applied.\nRestart now ?")
|
||||
messageLabel:SetContentAlignment(5)
|
||||
messageLabel:SetWrap(true)
|
||||
|
||||
local buttonGrid = vgui.Create("DGrid", frame)
|
||||
buttonGrid:Dock(BOTTOM)
|
||||
buttonGrid:DockMargin(5, 10, 5, 5)
|
||||
buttonGrid:SetCols(2)
|
||||
buttonGrid:SetColWide(frame:GetWide() / 2 - 10)
|
||||
buttonGrid:SetRowHeight(35)
|
||||
|
||||
local button = vgui.Create("DButton")
|
||||
button:SetText("Restart")
|
||||
button.DoClick = function()
|
||||
frame:Close()
|
||||
gmInte.SendNet("restartMap")
|
||||
end
|
||||
button:SetSize(buttonGrid:GetColWide(), buttonGrid:GetRowHeight())
|
||||
buttonGrid:AddItem(button)
|
||||
|
||||
local button = vgui.Create("DButton")
|
||||
button:SetText("Maybe Later")
|
||||
button.DoClick = function()
|
||||
frame:Close()
|
||||
end
|
||||
button:SetSize(buttonGrid:GetColWide(), buttonGrid:GetRowHeight())
|
||||
buttonGrid:AddItem(button)
|
||||
end
|
||||
|
||||
function gmInte.openConfigMenu(data)
|
||||
local needRestart = false
|
||||
|
||||
local frame = vgui.Create("DFrame")
|
||||
frame:SetSize(400, (600 / 1080) * ScrH())
|
||||
frame:Center()
|
||||
frame:SetTitle("Gmod Integration - Server Config")
|
||||
frame:SetDraggable(true)
|
||||
frame:ShowCloseButton(true)
|
||||
frame:MakePopup()
|
||||
|
||||
local scrollPanel = vgui.Create("DScrollPanel", frame)
|
||||
scrollPanel:Dock(FILL)
|
||||
|
||||
local messagePanel = vgui.Create("DPanel", scrollPanel)
|
||||
messagePanel:Dock(TOP)
|
||||
messagePanel:SetSize(300, 60)
|
||||
messagePanel:DockMargin(10, 0, 10, 10)
|
||||
messagePanel:SetBackgroundColor(Color(0, 0, 0, 0))
|
||||
|
||||
local messageLabel = vgui.Create("DLabel", messagePanel)
|
||||
messageLabel:Dock(FILL)
|
||||
messageLabel:SetText("This config is superior to the webpanel config.\nIf you change something here you can override the webpanel config.\nSome features require a websocket connection to work properly.")
|
||||
messageLabel:SetWrap(true)
|
||||
|
||||
for k, catName in pairs(configCat) do
|
||||
local collapsibleCategory = vgui.Create("DCollapsibleCategory", scrollPanel)
|
||||
collapsibleCategory:Dock(TOP)
|
||||
collapsibleCategory:DockMargin(10, 0, 10, 10)
|
||||
collapsibleCategory:SetLabel(catName)
|
||||
collapsibleCategory:SetExpanded(true)
|
||||
|
||||
local configList = vgui.Create("DPanelList", collapsibleCategory)
|
||||
configList:Dock(FILL)
|
||||
configList:SetSpacing(5)
|
||||
configList:EnableHorizontal(false)
|
||||
configList:EnableVerticalScrollbar(false)
|
||||
collapsibleCategory:SetContents(configList)
|
||||
|
||||
local categoryConfig = {}
|
||||
for k, v in pairs(possibleConfig) do
|
||||
if v.category == catName then
|
||||
table.insert(categoryConfig, v)
|
||||
end
|
||||
end
|
||||
|
||||
// Sort by position
|
||||
table.sort(categoryConfig, function(a, b)
|
||||
return (a.position || 0) < (b.position || 0)
|
||||
end)
|
||||
|
||||
for k, actualConfig in pairs(categoryConfig) do
|
||||
local panel = vgui.Create("DPanel", configList)
|
||||
panel:Dock(TOP)
|
||||
panel:SetSize(300, 25)
|
||||
panel:SetBackgroundColor(Color(0, 0, 0, 0))
|
||||
|
||||
local label = vgui.Create("DLabel", panel)
|
||||
label:Dock(LEFT)
|
||||
label:SetSize(140, 25)
|
||||
label:SetText(actualConfig.label)
|
||||
label:SetContentAlignment(4)
|
||||
|
||||
local input
|
||||
|
||||
if actualConfig.type == "textEntry" then
|
||||
input = vgui.Create("DTextEntry", panel)
|
||||
input:SetText(actualConfig.value(actualConfig.id, data[actualConfig.id] || ""))
|
||||
local isLastID = 0
|
||||
input.OnChange = function(self)
|
||||
isLastID = isLastID + 1
|
||||
local isLocalLastID = isLastID
|
||||
timer.Simple(actualConfig.onEditDelay || 0.5, function()
|
||||
if isLocalLastID == isLastID then
|
||||
actualConfig.onEdit(actualConfig.id, self:GetValue())
|
||||
end
|
||||
end)
|
||||
end
|
||||
elseif (actualConfig.type == "checkbox") then
|
||||
input = vgui.Create("DComboBox", panel)
|
||||
if (actualConfig.condition && !actualConfig.condition(data)) then
|
||||
input:SetEnabled(false)
|
||||
end
|
||||
input:AddChoice("Enabled")
|
||||
input:AddChoice("Disabled")
|
||||
input:SetText(actualConfig.value(actualConfig.id, data[actualConfig.id]) && "Enabled" || "Disabled")
|
||||
input.OnSelect = function(self, index, value)
|
||||
if (actualConfig.restart) then
|
||||
needRestart = true
|
||||
end
|
||||
actualConfig.onEdit(actualConfig.id, value)
|
||||
end
|
||||
end
|
||||
|
||||
input:Dock(FILL)
|
||||
input:SetSize(150, 25)
|
||||
|
||||
if (actualConfig.description) then
|
||||
if (actualConfig.websocket && !data.websocket) then
|
||||
actualConfig.description = actualConfig.description .. "\n\nThis feature require a websocket connection to work properly."
|
||||
end
|
||||
if (actualConfig.disable) then
|
||||
actualConfig.description = actualConfig.description .. "\n\nThis feature will be available soon."
|
||||
end
|
||||
input:SetTooltip(actualConfig.description)
|
||||
end
|
||||
|
||||
configList:AddItem(panel)
|
||||
end
|
||||
end
|
||||
|
||||
local buttonGrid = vgui.Create("DGrid", frame)
|
||||
buttonGrid:Dock(BOTTOM)
|
||||
buttonGrid:DockMargin(5, 10, 5, 5)
|
||||
buttonGrid:SetCols(2)
|
||||
buttonGrid:SetColWide(frame:GetWide() / 2 - 10)
|
||||
buttonGrid:SetRowHeight(35)
|
||||
|
||||
local buttonsCount = 0
|
||||
for k, v in pairs(buttonsInfo) do
|
||||
if (v.condition && !v.condition(data)) then continue end
|
||||
local button = vgui.Create("DButton")
|
||||
button:SetText(v.label)
|
||||
button.DoClick = function()
|
||||
v.func(data)
|
||||
end
|
||||
button:SetSize(buttonGrid:GetColWide(), buttonGrid:GetRowHeight())
|
||||
buttonGrid:AddItem(button)
|
||||
buttonsCount = buttonsCount + 1
|
||||
end
|
||||
|
||||
if (buttonsCount % 2 == 1) then
|
||||
local lastButton = buttonGrid:GetItems()[buttonsCount]
|
||||
lastButton:SetWide(frame:GetWide() - 20)
|
||||
end
|
||||
|
||||
frame.OnClose = function()
|
||||
if (needRestart) then gmInte.needRestart() end
|
||||
end
|
||||
end
|
65
lua/gmod_integration/client/cl_gui_link.lua
Normal file
65
lua/gmod_integration/client/cl_gui_link.lua
Normal file
|
@ -0,0 +1,65 @@
|
|||
function gmInte.openVerifPopup()
|
||||
local frame = vgui.Create("DFrame")
|
||||
frame:SetSize(400, 200)
|
||||
frame:Center()
|
||||
frame:SetTitle("Gmod Integration - Verification Required")
|
||||
frame:SetDraggable(false)
|
||||
frame:ShowCloseButton(false)
|
||||
frame:MakePopup()
|
||||
frame.Paint = function(self, w, h)
|
||||
draw.RoundedBox(8, 0, 0, w, h, gmInte.getColor("background"))
|
||||
end
|
||||
|
||||
local messageLabel = vgui.Create("DLabel", frame)
|
||||
messageLabel:Dock(FILL)
|
||||
messageLabel:DockMargin(10, 0, 10, 0)
|
||||
messageLabel:SetText("Hey,\nIt looks like you haven't linked your Steam account to Discord yet. This is required to play on this server. Please click the button below to link your account.\n\nAfter you've done that, click the refresh button.")
|
||||
messageLabel:SetContentAlignment(5)
|
||||
messageLabel:SetFont("GmodIntegration_Roboto_16")
|
||||
messageLabel:SetWrap(true)
|
||||
|
||||
local buttonGrid = vgui.Create("DGrid", frame)
|
||||
buttonGrid:Dock(BOTTOM)
|
||||
buttonGrid:DockMargin(10, 0, 10, 10)
|
||||
buttonGrid:SetCols(2)
|
||||
buttonGrid:SetColWide(frame:GetWide() / 2 - 10)
|
||||
buttonGrid:SetRowHeight(35)
|
||||
|
||||
local button = vgui.Create("DButton")
|
||||
button:SetText("Open Verification Page")
|
||||
button.DoClick = function()
|
||||
gui.OpenURL("https://verif.gmod-integration.com")
|
||||
end
|
||||
button:SetSize(buttonGrid:GetColWide() - 10, buttonGrid:GetRowHeight())
|
||||
buttonGrid:AddItem(button)
|
||||
button:SetTextColor(Color(255, 255, 255))
|
||||
button.Paint = function(self, w, h)
|
||||
local color = gmInte.getColor("primary")
|
||||
if self:IsHovered() then
|
||||
color = gmInte.getColor("primary-active")
|
||||
end
|
||||
draw.RoundedBox(8, 0, 0, w, h, color)
|
||||
end
|
||||
|
||||
local button = vgui.Create("DButton")
|
||||
button:SetText("Refresh Verification")
|
||||
button.DoClick = function()
|
||||
gmInte.http.get("/users/" .. LocalPlayer():SteamID64(), function(code, body)
|
||||
gmInte.SendNet("verifyMe")
|
||||
frame:Close()
|
||||
end,
|
||||
function(err)
|
||||
LocalPlayer():ChatPrint("Failed to refresh verification: " .. err)
|
||||
end)
|
||||
end
|
||||
button:SetSize(buttonGrid:GetColWide() - 10, buttonGrid:GetRowHeight())
|
||||
buttonGrid:AddItem(button)
|
||||
button:SetTextColor(Color(255, 255, 255))
|
||||
button.Paint = function(self, w, h)
|
||||
local color = gmInte.getColor("primary")
|
||||
if self:IsHovered() then
|
||||
color = gmInte.getColor("primary-active")
|
||||
end
|
||||
draw.RoundedBox(8, 0, 0, w, h, color)
|
||||
end
|
||||
end
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
// Player Finish Init
|
||||
hook.Add("InitPostEntity", "gmInte:Ply:Ready", function()
|
||||
gmInte.SendNet(0)
|
||||
gmInte.SendNet("ready")
|
||||
end)
|
||||
|
||||
hook.Add("OnPlayerChat", "gmInte:OnPlayerChat:AdminCmd", function(ply, strText, bTeamOnly, bPlayerIsDead)
|
||||
|
@ -12,7 +12,7 @@ hook.Add("OnPlayerChat", "gmInte:OnPlayerChat:AdminCmd", function(ply, strText,
|
|||
|
||||
strText = string.lower(strText)
|
||||
|
||||
if (strText == "/gminte") then
|
||||
if (strText == "/gmi") then
|
||||
gmInte.openAdminConfig()
|
||||
return true
|
||||
end
|
||||
|
|
|
@ -2,18 +2,13 @@
|
|||
// Main
|
||||
//
|
||||
|
||||
local function formatName(name)
|
||||
// all un down case
|
||||
name = string.lower(name)
|
||||
// first leter in upper case
|
||||
name = string.upper(string.sub(name, 1, 1)) .. string.sub(name, 2)
|
||||
// every letter after a space in upper case
|
||||
name = string.gsub(name, "(%a)([%w_']*)", function(a,b) return string.upper(a) .. string.lower(b) end)
|
||||
return name
|
||||
end
|
||||
|
||||
function gmInte.discordSyncChatPly(data)
|
||||
chat.AddText(Color(92, 105, 255), "(DISCORD) ", Color(12, 151, 12), formatName(data.name) .. ": ", Color(255, 255, 255), data.content)
|
||||
function gmInte.chatAddText(data)
|
||||
local args = {}
|
||||
for _, v in ipairs(data) do
|
||||
table.insert(args, v.color)
|
||||
table.insert(args, v.text)
|
||||
end
|
||||
chat.AddText(unpack(args))
|
||||
end
|
||||
|
||||
function gmInte.showTestConnection(data)
|
||||
|
@ -30,49 +25,7 @@ function gmInte.openAdminConfig()
|
|||
return
|
||||
end
|
||||
|
||||
gmInte.SendNet(2)
|
||||
end
|
||||
|
||||
local ScreenshotRequested = false
|
||||
hook.Add("PostRender", "gmInteScreenshot", function()
|
||||
if (!ScreenshotRequested) then return end
|
||||
ScreenshotRequested = false
|
||||
|
||||
local captureData = {
|
||||
format = "png",
|
||||
x = 0,
|
||||
y = 0,
|
||||
w = ScrW(),
|
||||
h = ScrH()
|
||||
}
|
||||
|
||||
local screenCapture = render.Capture(captureData)
|
||||
screenCapture = util.Base64Encode(screenCapture)
|
||||
gmInte.log("Screenshot Taken - " .. string.len(#screenCapture / 1024) .. "KB", true)
|
||||
|
||||
gmInte.post("/player/screenshots",
|
||||
{
|
||||
["steamID64"] = LocalPlayer():SteamID64(),
|
||||
["screenshot"] = screenCapture,
|
||||
["options"] = captureData,
|
||||
["name"] = LocalPlayer():Nick()
|
||||
},
|
||||
function(code, body)
|
||||
gmInte.log("Screenshot sent to Discord", true)
|
||||
end,
|
||||
function(code, body)
|
||||
gmInte.log("Screenshot failed to send to Discord, error code: " .. code, true)
|
||||
end
|
||||
)
|
||||
end)
|
||||
|
||||
function gmInte.takeScreenShot(serverID, authToken)
|
||||
gmInte.config.id = serverID
|
||||
gmInte.config.token = authToken
|
||||
|
||||
timer.Simple(0.2, function()
|
||||
ScreenshotRequested = true
|
||||
end)
|
||||
gmInte.SendNet("getConfig")
|
||||
end
|
||||
|
||||
//
|
||||
|
@ -80,20 +33,3 @@ end
|
|||
//
|
||||
|
||||
concommand.Add("gmod_integration_admin", gmInte.openAdminConfig)
|
||||
concommand.Add("gmod_integration_screenshot", function()
|
||||
gmInte.SendNet(4)
|
||||
end)
|
||||
|
||||
//
|
||||
// Chat Commands
|
||||
//
|
||||
|
||||
hook.Add("OnPlayerChat", "gmInteChatCommands", function(ply, text, teamChat, isDead)
|
||||
if (ply != LocalPlayer()) then return end
|
||||
text = string.lower(text)
|
||||
text = string.sub(text, 2)
|
||||
|
||||
if (text == "screen") then
|
||||
gmInte.SendNet(4)
|
||||
end
|
||||
end)
|
|
@ -1,33 +1,30 @@
|
|||
//
|
||||
// Network
|
||||
// Send Net
|
||||
//
|
||||
|
||||
/*
|
||||
Upload
|
||||
0 - Say I'm ready
|
||||
1 - Test Connection
|
||||
2 - Get Config
|
||||
3 - Save Config
|
||||
4 - Take ScreenShot
|
||||
5 - Restart Map
|
||||
Receive
|
||||
1 - Sync Chat
|
||||
2 - Get Config
|
||||
3 - Test Connection
|
||||
4 - Take ScreenShot
|
||||
*/
|
||||
local netSend = {
|
||||
["ready"] = 0,
|
||||
["testConnection"] = 1,
|
||||
["getConfig"] = 2,
|
||||
["saveConfig"] = 3,
|
||||
["takeScreenShot"] = 4,
|
||||
["restartMap"] = 5,
|
||||
["verifyMe"] = 6,
|
||||
}
|
||||
|
||||
// Send
|
||||
function gmInte.SendNet(id, args, func)
|
||||
net.Start("gmIntegration")
|
||||
net.WriteUInt(id, 8)
|
||||
net.WriteUInt(netSend[id], 8)
|
||||
net.WriteString(util.TableToJSON(args || {}))
|
||||
if (func) then func() end
|
||||
net.SendToServer()
|
||||
end
|
||||
|
||||
// Receive
|
||||
local netFunc = {
|
||||
//
|
||||
// Receive Net
|
||||
//
|
||||
|
||||
local netReceive = {
|
||||
[1] = function(data)
|
||||
gmInte.discordSyncChatPly(data)
|
||||
end,
|
||||
|
@ -37,13 +34,22 @@ local netFunc = {
|
|||
[3] = function(data)
|
||||
gmInte.showTestConnection(data)
|
||||
end,
|
||||
[4] = function(data)
|
||||
gmInte.takeScreenShot(data.serverID, data.authToken)
|
||||
[5] = function(data)
|
||||
gmInte.config = table.Merge(gmInte.config, data)
|
||||
end,
|
||||
[6] = function(data)
|
||||
gmInte.chatAddText(data)
|
||||
end,
|
||||
[7] = function()
|
||||
gmInte.openVerifPopup()
|
||||
end,
|
||||
[8] = function(data)
|
||||
gmInte.config.token = data.token
|
||||
end
|
||||
}
|
||||
|
||||
net.Receive("gmIntegration", function()
|
||||
local id = net.ReadUInt(8)
|
||||
local args = util.JSONToTable(net.ReadString())
|
||||
if (netFunc[id]) then netFunc[id](args) end
|
||||
if (netReceive[id]) then netReceive[id](args) end
|
||||
end)
|
89
lua/gmod_integration/client/cl_screenshots.lua
Normal file
89
lua/gmod_integration/client/cl_screenshots.lua
Normal file
|
@ -0,0 +1,89 @@
|
|||
//
|
||||
// Hooks
|
||||
//
|
||||
|
||||
local ScreenshotRequested = false
|
||||
local FailAttempts = 0
|
||||
hook.Add("PostRender", "gmInteScreenshot", function()
|
||||
if (!ScreenshotRequested) then return end
|
||||
ScreenshotRequested = false
|
||||
|
||||
local captureData = {
|
||||
format = "jpeg",
|
||||
x = 0,
|
||||
y = 0,
|
||||
w = ScrW(),
|
||||
h = ScrH(),
|
||||
quality = 95,
|
||||
}
|
||||
|
||||
local screenCapture = render.Capture(captureData)
|
||||
if (!screenCapture) then
|
||||
if (FailAttempts < 3) then
|
||||
timer.Simple(0.5, function()
|
||||
ScreenshotRequested = true
|
||||
FailAttempts = FailAttempts + 1
|
||||
gmInte.log("Failed to take screenshot, retrying... (" .. FailAttempts .. "/3)", true)
|
||||
end)
|
||||
return
|
||||
else
|
||||
FailAttempts = 0
|
||||
chat.AddText(Color(255, 130, 92), "[Gmod Integration] ", Color(102, 63, 63), "Failed to take screenshot, your system may not support this feature.")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local base64Capture = util.Base64Encode(screenCapture)
|
||||
|
||||
local size = math.Round(string.len(base64Capture) / 1024)
|
||||
gmInte.log("Screenshot Taken - " .. size .. "KB", true)
|
||||
|
||||
gmInte.http.post("/screenshots",
|
||||
{
|
||||
["player"] = gmInte.getPlayerFormat(LocalPlayer()),
|
||||
["screenshot"] = base64Capture,
|
||||
["captureData"] = captureData,
|
||||
["size"] = size .. "KB"
|
||||
},
|
||||
function(code, body)
|
||||
gmInte.log("Screenshot sent to Discord", true)
|
||||
chat.AddText(Color(255, 130, 92), "[Gmod Integration] ", Color(255, 255, 255), "Screenshot sent to Discord.")
|
||||
end,
|
||||
function(code, body)
|
||||
gmInte.log("Screenshot failed to send to Discord, error code: " .. code, true)
|
||||
end
|
||||
)
|
||||
end)
|
||||
|
||||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
function gmInte.takeScreenShot()
|
||||
timer.Simple(0.5, function()
|
||||
ScreenshotRequested = true
|
||||
end)
|
||||
end
|
||||
|
||||
//
|
||||
// Console Commands
|
||||
//
|
||||
|
||||
concommand.Add("gmod_integration_screenshot", function()
|
||||
gmInte.takeScreenShot()
|
||||
end)
|
||||
|
||||
//
|
||||
// Chat Commands
|
||||
//
|
||||
|
||||
hook.Add("OnPlayerChat", "gmInteChatCommands", function(ply, text, teamChat, isDead)
|
||||
if (ply != LocalPlayer()) then return end
|
||||
text = string.lower(text)
|
||||
text = string.sub(text, 2)
|
||||
|
||||
if (text == "screen") then
|
||||
gmInte.takeScreenShot()
|
||||
return true
|
||||
end
|
||||
end)
|
57
lua/gmod_integration/client/cl_steaming.lua
Normal file
57
lua/gmod_integration/client/cl_steaming.lua
Normal file
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// Hooks
|
||||
//
|
||||
|
||||
local StreamsRequeted = false
|
||||
hook.Add("PostRender", "gmInte:PostRender:Stream:Frame", function()
|
||||
if (!StreamsRequeted) then return end
|
||||
StreamsRequeted = false
|
||||
|
||||
// Capture frame
|
||||
local captureConfig = {
|
||||
format = "jpeg",
|
||||
x = 0,
|
||||
y = 0,
|
||||
w = ScrW(),
|
||||
h = ScrH(),
|
||||
quality = 30,
|
||||
}
|
||||
|
||||
local screenCapture = render.Capture(captureConfig)
|
||||
if (!screenCapture) then return end
|
||||
screenCapture = util.Base64Encode(screenCapture)
|
||||
|
||||
local size = math.Round(string.len(screenCapture) / 1024)
|
||||
gmInte.log("Frame captured, size: " .. size .. "KB", true)
|
||||
|
||||
gmInte.http.post("/streams/frames",
|
||||
{
|
||||
["player"] = gmInte.getPlayerFormat(LocalPlayer()),
|
||||
["base64Capture"] = screenCapture,
|
||||
["captureConfig"] = captureConfig,
|
||||
["size"] = size .. "KB"
|
||||
},
|
||||
function(code, body)
|
||||
gmInte.log("Frame sent to WebPanel, size: " .. size .. "KB", true)
|
||||
end,
|
||||
function(code, body)
|
||||
gmInte.log("Failed to send frame to WebPanel", true)
|
||||
end
|
||||
)
|
||||
end)
|
||||
|
||||
local Steam = false
|
||||
timer.Create("gmInte:Stream:Frame", 0.5, 0, function()
|
||||
if (Steam) then
|
||||
StreamsRequeted = true
|
||||
end
|
||||
end)
|
||||
|
||||
//
|
||||
// Console Commands
|
||||
//
|
||||
|
||||
concommand.Add("gmod_integration_stream", function()
|
||||
Steam = !Steam
|
||||
gmInte.log("Streaming frames to WebPanel: " .. tostring(Steam))
|
||||
end)
|
13
lua/gmod_integration/client/cl_sync_chat.lua
Normal file
13
lua/gmod_integration/client/cl_sync_chat.lua
Normal file
|
@ -0,0 +1,13 @@
|
|||
local function formatName(name)
|
||||
// all un down case
|
||||
name = string.lower(name)
|
||||
// first leter in upper case
|
||||
name = string.upper(string.sub(name, 1, 1)) .. string.sub(name, 2)
|
||||
// every letter after a space in upper case
|
||||
name = string.gsub(name, "(%a)([%w_']*)", function(a,b) return string.upper(a) .. string.lower(b) end)
|
||||
return name
|
||||
end
|
||||
|
||||
function gmInte.discordSyncChatPly(data)
|
||||
chat.AddText(Color(92, 105, 255), "(DISCORD) ", Color(12, 151, 12), formatName(data.name) .. ": ", Color(255, 255, 255), data.content)
|
||||
end
|
|
@ -30,16 +30,7 @@ if (!GWSockets) then
|
|||
end
|
||||
|
||||
local function getWebSocketURL()
|
||||
local url = "wss://ws.gmod-integration.com"
|
||||
local devURL = "wss://dev-ws.gmod-integration.com"
|
||||
|
||||
if (!gmInte.config.debug) then return url end
|
||||
if (gmInte.config.devInstance) then
|
||||
gmInte.log("Using dev Instance", true)
|
||||
return devURL
|
||||
end
|
||||
|
||||
return url
|
||||
return "wss://" .. gmInte.config.websocketFQDN
|
||||
end
|
||||
|
||||
local socket = GWSockets.createWebSocket(getWebSocketURL())
|
||||
|
@ -55,14 +46,12 @@ end
|
|||
// log on message
|
||||
function socket:onMessage(txt)
|
||||
gmInte.log("WebSocket Message: " .. txt, true)
|
||||
|
||||
local data = util.JSONToTable(txt)
|
||||
if (gmInte.config.debug) then
|
||||
gmInte.log("WebSocket Message: " .. txt, true)
|
||||
end
|
||||
if (gmInte[data.method]) then
|
||||
gmInte[data.method](data)
|
||||
else
|
||||
gmInte.logError("WebSocket Message: " .. txt .. " is not a valid method !")
|
||||
gmInte.logError("WebSocket Message: " .. txt .. " is not a valid method !", true)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
//
|
||||
// Console Commands
|
||||
//
|
||||
|
||||
local conFuncs = {
|
||||
["version"] = function()
|
||||
gmInte.log("Version: " .. gmInte.version)
|
||||
|
|
86
lua/gmod_integration/server/sv_filtrers.lua
Normal file
86
lua/gmod_integration/server/sv_filtrers.lua
Normal file
|
@ -0,0 +1,86 @@
|
|||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
local function filterMessage(reason)
|
||||
local Message = {
|
||||
"\n----------------------------------------\n",
|
||||
"You cannot join this server",
|
||||
"",
|
||||
"Reason: " .. (reason && reason || "none"),
|
||||
"Help URL: " .. (gmInte.config.supportLink && gmInte.config.supportLink || "none"),
|
||||
"",
|
||||
"Have a nice day",
|
||||
"\n----------------------------------------\n",
|
||||
"Service provided by Gmod Integration",
|
||||
}
|
||||
|
||||
for k, v in pairs(Message) do
|
||||
Message[k] = "\n" .. v
|
||||
end
|
||||
|
||||
return table.concat(Message)
|
||||
end
|
||||
|
||||
local function checkTrustFactor(trustLevel)
|
||||
if (gmInte.config.filterOnTrust && (trustLevel < gmInte.config.minimalTrust)) then
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local function checkBanStatus(banStatus)
|
||||
if (gmInte.config.filterOnBan && banStatus) then
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local function checkDiscordBanStatus(banStatus)
|
||||
if (gmInte.config.syncBan && banStatus) then
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local function playerFilter(data)
|
||||
if (data.bot == 1) then return end
|
||||
data.steamID64 = util.SteamIDTo64(data.networkid)
|
||||
|
||||
gmInte.http.get("/players/" .. data.steamID64,
|
||||
function(code, body)
|
||||
if (gmInte.config.maintenance && !body.bypassMaintenance) then
|
||||
game.KickID(data.networkid, filterMessage("The server is currently under maintenance and you are not whitelisted."))
|
||||
end
|
||||
|
||||
if (!checkBanStatus(body.ban)) then
|
||||
game.KickID(data.networkid, filterMessage("You are banned from this server."))
|
||||
end
|
||||
|
||||
if (!checkDiscordBanStatus(body.discord_ban)) then
|
||||
game.KickID(data.networkid, filterMessage("You are banned from our discord server."))
|
||||
end
|
||||
|
||||
-- if (!checkTrustFactor(body.trust)) then
|
||||
-- game.KickID(data.networkid, filterMessage("Your trust factor is too low."))
|
||||
-- end
|
||||
end,
|
||||
function (code, body)
|
||||
if (gmInte.config.maintenance) then
|
||||
game.KickID(data.networkid, filterMessage("The server is currently under maintenance and we cannot verify your account.\nVerification URL: https://verif.gmod-integration.com"))
|
||||
end
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
//
|
||||
// Hooks
|
||||
//
|
||||
|
||||
gameevent.Listen("player_connect")
|
||||
hook.Add("player_connect", "gmInte:Player:Connect:Filter", function(data)
|
||||
playerFilter(data)
|
||||
end)
|
|
@ -1,40 +0,0 @@
|
|||
//
|
||||
// Server Hooks
|
||||
//
|
||||
|
||||
hook.Add("ShutDown", "gmInte:Server:ShutDown", function()
|
||||
gmInte.serverShutDown()
|
||||
end)
|
||||
|
||||
hook.Add("Initialize", "gmInte.sendStatus", function()
|
||||
timer.Simple(1, function()
|
||||
gmInte.serverStart()
|
||||
end)
|
||||
end)
|
||||
|
||||
//
|
||||
// Player Hooks
|
||||
//
|
||||
|
||||
gameevent.Listen("player_connect")
|
||||
hook.Add("player_connect", "gmInte:Player:Connect", function(data)
|
||||
gmInte.playerConnect(data)
|
||||
gmInte.playerFilter(data)
|
||||
end)
|
||||
|
||||
gameevent.Listen("server_addban")
|
||||
hook.Add("server_addban", "gmInte:Player:Ban", function(data)
|
||||
gmInte.playerBan(data)
|
||||
end)
|
||||
|
||||
hook.Add("PlayerDisconnected", "gmInte:Player:Disconnect", function(ply)
|
||||
gmInte.playerDisconnected(ply)
|
||||
end)
|
||||
|
||||
hook.Add("onPlayerChangedName", "gmInte:PlayerChangeName", function(ply, old, new)
|
||||
gmInte.playerChangeName(ply, old, new)
|
||||
end)
|
||||
|
||||
hook.Add("PlayerSay", "gmInte:PlayerSay", function(ply, text, team)
|
||||
gmInte.playerSay(ply, text, team)
|
||||
end)
|
|
@ -1,248 +0,0 @@
|
|||
//
|
||||
// Functions
|
||||
//
|
||||
|
||||
local function logFormatWeapon(weapon, data)
|
||||
data = data or {}
|
||||
data.class = weapon:GetClass()
|
||||
data.printName = weapon:GetPrintName()
|
||||
return data
|
||||
end
|
||||
|
||||
local function logFormatEntity(ent, data)
|
||||
data = data or {}
|
||||
data.class = ent:GetClass()
|
||||
data.model = ent:GetModel()
|
||||
data.pos = ent:GetPos()
|
||||
data.ang = ent:GetAngles()
|
||||
return data
|
||||
end
|
||||
|
||||
local function logFormatVector(vec, data)
|
||||
data = data or {}
|
||||
data.x = vec.x
|
||||
data.y = vec.y
|
||||
data.z = vec.z
|
||||
return data
|
||||
end
|
||||
|
||||
local function logFormatAngle(ang, data)
|
||||
data = data or {}
|
||||
data.p = ang.p
|
||||
data.y = ang.y
|
||||
data.r = ang.r
|
||||
return data
|
||||
end
|
||||
|
||||
local function logFormatTeam(teamID, data)
|
||||
data = data or {}
|
||||
data.id = teamID
|
||||
data.name = team.GetName(teamID)
|
||||
return data
|
||||
end
|
||||
|
||||
local function logFormatPlayer(ply, data)
|
||||
data = data or {}
|
||||
data.steamID64 = ply:SteamID64()
|
||||
data.steamID = ply:SteamID()
|
||||
data.nick = ply:Nick()
|
||||
data.userGroup = ply:GetUserGroup()
|
||||
data.team = logFormatTeam(ply:Team())
|
||||
return data
|
||||
end
|
||||
|
||||
local function logDisable()
|
||||
return !gmInte.config.sendLog
|
||||
end
|
||||
|
||||
local function validLogAndPlayers(players)
|
||||
if (logDisable()) then return false end
|
||||
for _, ply in pairs(players) do
|
||||
// return if not valid, player or bot and bots logs are disabled
|
||||
if (!IsValid(ply)) then return false end
|
||||
if (!ply:IsPlayer()) then return false end
|
||||
if (!ply:IsBot() && !gmInte.config.logBotActions) then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
//
|
||||
// Posts
|
||||
//
|
||||
|
||||
function gmInte.postLogPlayerSay(ply, text, teamChat)
|
||||
if (!validLogAndPlayers({ply})) then return end
|
||||
|
||||
gmInte.post("/server/log/playerSay",
|
||||
{
|
||||
["ply"] = logFormatPlayer(ply),
|
||||
["text"] = text,
|
||||
["teamChat"] = teamChat
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function gmInte.postLogPlayerDeath(ply, inflictor, attacker)
|
||||
if (!validLogAndPlayers({ply, attacker})) then return end
|
||||
|
||||
gmInte.post("/server/log/playerDeath",
|
||||
{
|
||||
["ply"] = logFormatPlayer(ply),
|
||||
["inflictor"] = logFormatEntity(inflictor),
|
||||
["attacker"] = logFormatPlayer(attacker)
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function gmInte.postLogPlayerInitialSpawn(ply)
|
||||
if (!validLogAndPlayers({ply})) then return end
|
||||
|
||||
gmInte.post("/server/log/playerInitialSpawn",
|
||||
{
|
||||
["ply"] = logFormatPlayer(ply)
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function gmInte.postLogPlayerHurt(ply, attacker, healthRemaining, damageTaken)
|
||||
if (!validLogAndPlayers({ply, attacker})) then return end
|
||||
|
||||
// Wait a second to see if the player is going to be hurt again
|
||||
ply.gmodInteLastHurt = ply.gmodInteLastHurt || {}
|
||||
local locCurTime = CurTime()
|
||||
ply.gmodInteLastHurt[attacker:SteamID64()] = locCurTime
|
||||
|
||||
timer.Simple(1, function()
|
||||
if (ply.gmodInteLastHurt[attacker:SteamID64()] != locCurTime) then
|
||||
ply.gmodInteTotalDamage = ply.gmodInteTotalDamage || 0
|
||||
ply.gmodInteTotalDamage = ply.gmodInteTotalDamage + damageTaken
|
||||
return
|
||||
end
|
||||
|
||||
gmInte.post("/server/log/playerHurt",
|
||||
{
|
||||
["ply"] = logFormatPlayer(ply),
|
||||
["attacker"] = logFormatPlayer(attacker),
|
||||
["healthRemaining"] = healthRemaining,
|
||||
["damageTaken"] = ply.gmodInteTotalDamage
|
||||
}
|
||||
)
|
||||
end)
|
||||
end
|
||||
|
||||
function gmInte.postLogPlayerSpawnedSomething(object, ply, ent, model)
|
||||
if (!validLogAndPlayers({ply})) then return end
|
||||
|
||||
gmInte.post("/server/log/playerSpawnedSomething",
|
||||
{
|
||||
["object"] = object,
|
||||
["ply"] = logFormatPlayer(ply),
|
||||
["ent"] = logFormatEntity(ent),
|
||||
["model"] = model || ""
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function gmInte.postLogPlayerSpawn(ply)
|
||||
if (!validLogAndPlayers({ply})) then return end
|
||||
|
||||
gmInte.post("/server/log/playerSpawn",
|
||||
{
|
||||
["ply"] = logFormatPlayer(ply)
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function gmInte.postLogPlayerDisconnect(ply)
|
||||
if (!validLogAndPlayers({ply})) then return end
|
||||
|
||||
gmInte.post("/server/log/playerDisconnect",
|
||||
{
|
||||
["ply"] = logFormatPlayer(ply)
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function gmInte.postLogPlayerConnect(data)
|
||||
if (logDisable() || data.bot) then return end
|
||||
|
||||
gmInte.post("/server/log/playerConnect",
|
||||
{
|
||||
["steamID64"] = util.SteamIDTo64(data.networkid),
|
||||
["steamID"] = data.networkid,
|
||||
["name"] = data.name,
|
||||
["ip"] = data.address
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function gmInte.postLogPlayerGivet(ply, class, swep)
|
||||
if (!validLogAndPlayers({ply})) then return end
|
||||
|
||||
gmInte.post("/server/log/playerGive",
|
||||
{
|
||||
["ply"] = logFormatPlayer(ply),
|
||||
["class"] = class,
|
||||
["swep"] = swep
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
//
|
||||
// Hooks
|
||||
//
|
||||
|
||||
gameevent.Listen("player_connect")
|
||||
|
||||
// Sandbox - Player
|
||||
hook.Add("PlayerSay", "gmInte:Log:PlayerSay", function(ply, text, teamChat)
|
||||
gmInte.postLogPlayerSay(ply, text, teamChat)
|
||||
end)
|
||||
hook.Add("PlayerSpawn", "gmInte:Log:PlayerSpawn", function(ply)
|
||||
gmInte.postLogPlayerSpawn(ply)
|
||||
end)
|
||||
hook.Add("PlayerInitialSpawn", "gmInte:Log:PlayerInitialSpawn", function(ply)
|
||||
gmInte.postLogPlayerInitialSpawn(ply)
|
||||
end)
|
||||
hook.Add("PlayerDisconnected", "gmInte:Log:PlayerDisconnected", function(ply)
|
||||
gmInte.postLogPlayerDisconnect(ply)
|
||||
end)
|
||||
hook.Add("PlayerGiveSWEP", "gmInte:Log:PlayerSWEPs", function( ply, class, swep )
|
||||
gmInte.postLogPlayerGivet(ply, class, swep)
|
||||
end)
|
||||
|
||||
// Sandbox - Server Events
|
||||
hook.Add("player_connect", "gmInte:Log:PlayerConnect", function(data)
|
||||
gmInte.postLogPlayerConnect(data)
|
||||
end)
|
||||
|
||||
// Sandbox - Player Combat
|
||||
hook.Add("PlayerDeath", "gmInte:Log:PlayerDeath", function(ply, inflictor, attacker)
|
||||
gmInte.postLogPlayerDeath(ply, inflictor, attacker)
|
||||
end)
|
||||
hook.Add("PlayerHurt", "gmInte:Log:PlayerHurt", function(ply, attacker, healthRemaining, damageTaken)
|
||||
gmInte.postLogPlayerHurt(ply, attacker, healthRemaining, damageTaken)
|
||||
end)
|
||||
|
||||
// Sandbox - Spawnables
|
||||
hook.Add("PlayerSpawnedProp", "gmInte:Log:PlayerSpawnedProp", function(ply, model, ent)
|
||||
gmInte.postLogPlayerSpawnedSomething("SENT", ply, ent, model)
|
||||
end)
|
||||
hook.Add("PlayerSpawnedSENT", "gmInte:Log:PlayerSpawnedSENT", function(ply, ent)
|
||||
gmInte.postLogPlayerSpawnedSomething("SENT", ply, ent)
|
||||
end)
|
||||
hook.Add("PlayerSpawnedNPC", "gmInte:Log:PlayerSpawnedNPC", function(ply, ent)
|
||||
gmInte.postLogPlayerSpawnedSomething("NPC", ply, ent)
|
||||
end)
|
||||
hook.Add("PlayerSpawnedVehicle", "gmInte:Log:PlayerSpawnedVehicle", function(ply, ent)
|
||||
gmInte.postLogPlayerSpawnedSomething("Vehicle", ply, ent)
|
||||
end)
|
||||
hook.Add("PlayerSpawnedEffect", "gmInte:Log:PlayerSpawnedEffect", function(ply, model, ent)
|
||||
gmInte.postLogPlayerSpawnedSomething("Effect", ply, ent, model)
|
||||
end)
|
||||
hook.Add("PlayerSpawnedRagdoll", "gmInte:Log:PlayerSpawnedRagdoll", function(ply, model, ent)
|
||||
gmInte.postLogPlayerSpawnedSomething("Ragdoll", ply, ent, model)
|
||||
end)
|
||||
hook.Add("PlayerSpawnedSWEP", "gmInte:Log:PlayerSpawnedSWEP", function(ply, ent)
|
||||
gmInte.postLogPlayerSpawnedSomething("SWEP", ply, ent)
|
||||
end)
|
|
@ -1,300 +0,0 @@
|
|||
//
|
||||
// Functions
|
||||
//
|
||||
|
||||
function gmInte.removePort(ip)
|
||||
return string.Explode(":", ip)[1]
|
||||
end
|
||||
|
||||
function gmInte.plyValid(ply)
|
||||
return ply:IsValid() && ply:IsPlayer() && !ply:IsBot()
|
||||
end
|
||||
|
||||
function gmInte.saveSetting(setting, value)
|
||||
// save this in data/gmod_integration/setting.json but first check if variable is valid
|
||||
if gmInte.config[setting] == nil then
|
||||
gmInte.log("Unknown Setting")
|
||||
return
|
||||
end
|
||||
|
||||
// Boolean
|
||||
if (value == "true") then value = true end
|
||||
if (value == "false") then value = false end
|
||||
|
||||
// Number
|
||||
if (tonumber(value) != nil) then value = tonumber(value) end
|
||||
|
||||
gmInte.config[setting] = value
|
||||
file.Write("gm_integration/config.json", util.TableToJSON(gmInte.config, true))
|
||||
gmInte.log("Setting Saved")
|
||||
end
|
||||
|
||||
function gmInte.playerConnect(data)
|
||||
if (data.bot == 1) then return end
|
||||
|
||||
data.steam = util.SteamIDTo64(data.networkid)
|
||||
|
||||
gmInte.post("/server/user/connect", data)
|
||||
end
|
||||
|
||||
local function getCustomValues(ply)
|
||||
local customValues = {}
|
||||
|
||||
customValues.money = ply:gmInteGetTotalMoney() || 0
|
||||
|
||||
return customValues
|
||||
end
|
||||
|
||||
local function getTriggerInfo(text)
|
||||
for k, v in pairs(gmInte.config.chatTrigger) do
|
||||
if (string.StartWith(text, k)) then
|
||||
local defaultConfig = {
|
||||
["trigger"] = k,
|
||||
["prefix"] = "",
|
||||
["show_rank"] = false,
|
||||
["anonymous"] = false,
|
||||
["channel"] = "admin_sync_chat"
|
||||
}
|
||||
for k2, v2 in pairs(v) do
|
||||
defaultConfig[k2] = v2
|
||||
end
|
||||
return defaultConfig
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function gmInte.playerSay(ply, text, team)
|
||||
if (!gmInte.config.syncChat) then return end
|
||||
|
||||
gmInte.post("/server/user/say",
|
||||
{
|
||||
["steamID64"] = ply:SteamID64(),
|
||||
["message"] = text,
|
||||
["name"] = ply:Nick(),
|
||||
["usergroup"] = ply:GetUserGroup(),
|
||||
["message_info"] = triggerInfo
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function gmInte.wsPlayerSay(data)
|
||||
gmInte.SendNet(1, data, nil)
|
||||
end
|
||||
|
||||
function gmInte.generatePlayerToken(steamID64)
|
||||
return util.SHA256(steamID64 .. '-' .. gmInte.config.token .. '-' .. gmInte.publicTempToken)
|
||||
end
|
||||
|
||||
function gmInte.takeScreenshot(ply)
|
||||
gmInte.SendNet(4, {
|
||||
["serverID"] = gmInte.config.id,
|
||||
["authToken"] = gmInte.generatePlayerToken(ply:SteamID64())
|
||||
}, ply)
|
||||
end
|
||||
|
||||
function gmInte.wsPlayerScreen(data)
|
||||
for _, ply in pairs(player.GetAll()) do
|
||||
if (ply:SteamID64() == data.steamID64) then
|
||||
gmInte.takeScreenshot(ply)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function gmInte.wsRcon(data)
|
||||
gmInte.log("Rcon Command from Discord '" .. data.command .. "' by " .. data.steamID)
|
||||
game.ConsoleCommand(data.command .. "\n")
|
||||
end
|
||||
|
||||
function gmInte.playerBan(data)
|
||||
data.steam = util.SteamIDTo64(data.networkid)
|
||||
gmInte.post("/server/user/ban", data)
|
||||
end
|
||||
|
||||
function gmInte.userFinishConnect(ply)
|
||||
if (!gmInte.plyValid(ply)) then return end
|
||||
|
||||
gmInte.post("/server/user/finishConnect",
|
||||
{
|
||||
["steam"] = ply:SteamID64(),
|
||||
["name"] = ply:Nick(),
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function gmInte.serverShutDown()
|
||||
gmInte.post("/server/shutdown")
|
||||
end
|
||||
|
||||
function gmInte.sendStatus(start)
|
||||
if (gmInte.config.id == "" || gmInte.config.token == "") then
|
||||
gmInte.logError("ID or Token is empty: (id: " .. (gmInte.config.id == "" && "empty" || gmInte.config.id) .. ", token: " .. (gmInte.config.token == "" && "empty" || "not empty but hide") .. ")")
|
||||
gmInte.logHint("Use 'gmod-integration setting id YOUR_SERVER_ID' and 'gmod-integration setting token YOUR_SERVER_TOKEN' to set your credentials, you can find them on https://gmod-integration.com/config/servers")
|
||||
return
|
||||
end
|
||||
gmInte.post("/server/status",
|
||||
{
|
||||
["start"] = start || false,
|
||||
["hostname"] = GetHostName(),
|
||||
["ip"] = game.GetIPAddress(),
|
||||
["port"] = GetConVar("hostport"):GetInt(),
|
||||
["map"] = game.GetMap(),
|
||||
["players"] = #player.GetAll(),
|
||||
["maxplayers"] = game.MaxPlayers(),
|
||||
["gamemode"] = engine.ActiveGamemode()
|
||||
},
|
||||
function(code, body)
|
||||
if (body.publicTempToken) then
|
||||
gmInte.publicTempToken = body.publicTempToken
|
||||
end
|
||||
end,
|
||||
function(code, body, headers)
|
||||
gmInte.logError("Your Credentials are Invalid: (id: " .. (gmInte.config.id == "" && "empty" || gmInte.config.id) .. ", token: " .. (gmInte.config.token == "" && "empty" || "not empty but hide") .. ")")
|
||||
gmInte.logHint("Use 'gmod-integration setting id YOUR_SERVER_ID' and 'gmod-integration setting token YOUR_SERVER_TOKEN' to set your credentials, you can find them on https://gmod-integration.com/config/servers")
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
function gmInte.serverStart()
|
||||
gmInte.sendStatus(true)
|
||||
end
|
||||
|
||||
// every 5 minutes
|
||||
timer.Create("gmInte.sendStatus", 300, 0, function()
|
||||
gmInte.sendStatus()
|
||||
end)
|
||||
|
||||
function gmInte.playerChangeName(ply, old, new)
|
||||
if (!gmInte.plyValid(ply)) then return end
|
||||
|
||||
gmInte.post("/server/user/changeName",
|
||||
{
|
||||
["steamID64"] = ply:SteamID64(),
|
||||
["oldName"] = old,
|
||||
["newName"] = new,
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function gmInte.playerDisconnected(ply)
|
||||
if (!gmInte.plyValid(ply)) then return end
|
||||
|
||||
gmInte.post("/server/user/disconnect",
|
||||
{
|
||||
["steam"] = ply:SteamID64(),
|
||||
["kills"] = ply:Frags() || 0,
|
||||
["deaths"] = ply:Deaths() || 0,
|
||||
["customValues"] = getCustomValues(ply),
|
||||
["rank"] = ply:GetUserGroup() || "user",
|
||||
["time"] = math.Round(RealTime() - ply.gmIntTimeConnect) || 0,
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function gmInte.tryConfig()
|
||||
gmInte.get("/server",
|
||||
function(code, body)
|
||||
print(" ")
|
||||
gmInte.log("Congratulations your server is now connected to Gmod Integration")
|
||||
gmInte.log("Server Name: " .. body.name)
|
||||
gmInte.log("Server ID: " .. body.id)
|
||||
print(" ")
|
||||
end)
|
||||
end
|
||||
|
||||
function gmInte.testConnection(ply)
|
||||
gmInte.get("/server",
|
||||
function(code, body)
|
||||
gmInte.SendNet(3, body, ply)
|
||||
end,
|
||||
function(code, body, headers)
|
||||
gmInte.SendNet(3, body, ply)
|
||||
end)
|
||||
end
|
||||
|
||||
function gmInte.serverShutDown()
|
||||
for ply, ply in pairs(player.GetAll()) do
|
||||
gmInte.playerDisconnected(ply)
|
||||
end
|
||||
end
|
||||
|
||||
function gmInte.refreshSettings()
|
||||
gmInte.config = util.JSONToTable(file.Read("gm_integration/config.json", "DATA"))
|
||||
gmInte.log("Settings Refreshed")
|
||||
gmInte.tryConfig()
|
||||
end
|
||||
|
||||
local function filterMessage(reason)
|
||||
local Message = {
|
||||
[1] = "\n",
|
||||
[2] = "This server has player filtering enabled",
|
||||
[3] = "You are not allowed to join this server",
|
||||
[4] = "",
|
||||
[5] = "Reason: " .. reason,
|
||||
[6] = "",
|
||||
[7] = "For more information, please contact the server owner",
|
||||
[8] = "Help URL: " .. (gmInte.config.supportLink && gmInte.config.supportLink || "No Support Link"),
|
||||
[9] = "",
|
||||
[10] = "You can also contact us on our discord server",
|
||||
[11] = "https://gmod-integration.com/discord",
|
||||
[12] = "",
|
||||
[13] = "Have a nice day",
|
||||
[14] = "",
|
||||
[15] = "Service provided by Gmod Integration",
|
||||
}
|
||||
for k, v in pairs(Message) do
|
||||
Message[k] = v .. "\n"
|
||||
end
|
||||
return table.concat(Message)
|
||||
end
|
||||
|
||||
function gmInte.playerFilter(data)
|
||||
if (data.bot == 1) then return end
|
||||
|
||||
data.steamID64 = util.SteamIDTo64(data.networkid)
|
||||
|
||||
// get data
|
||||
gmInte.get("/server/user" .. "?steamID64=" .. data.steamID64,
|
||||
function(code, body)
|
||||
if (!body || !body.trust) then return end
|
||||
|
||||
// Gmod Integration Trust
|
||||
if (gmInte.config.filterOnTrust && (body.trust < gmInte.config.minimalTrust)) then
|
||||
// kick player
|
||||
game.KickID(data.networkid, filterMessage("Insufficient Trust Level\nYour Trust Level: " .. body.trust .. "\nMinimal Trust Level: " .. gmInte.config.minimalTrust))
|
||||
end
|
||||
|
||||
// Gmod Integration Ban
|
||||
if (gmInte.config.filterOnBan && body.ban) then
|
||||
// kick player
|
||||
game.KickID(data.networkid, filterMessage("You are banned from Gmod Integration"))
|
||||
end
|
||||
|
||||
// Server Discord Ban
|
||||
if (gmInte.config.syncBan && body.discord_ban) then
|
||||
// kick player
|
||||
game.KickID(data.networkid, filterMessage("You are banned from the discord server\nReason: " .. (body.discord_ban_reason && body.discord_ban_reason || "No Reason")))
|
||||
end
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
function gmInte.superadminGetConfig(ply)
|
||||
if (!gmInte.plyValid(ply) || !ply:IsSuperAdmin()) then return end
|
||||
|
||||
gmInte.config.websocket = GWSockets && true || false
|
||||
gmInte.SendNet(2, gmInte.config, ply)
|
||||
end
|
||||
|
||||
function gmInte.superadminSetConfig(ply, data)
|
||||
if (!gmInte.plyValid(ply) || !ply:IsSuperAdmin()) then return end
|
||||
|
||||
for k, v in pairs(data) do
|
||||
gmInte.saveSetting(k, v)
|
||||
end
|
||||
|
||||
if data.token || data.id then
|
||||
gmInte.testConnection(ply)
|
||||
end
|
||||
end
|
|
@ -1,12 +0,0 @@
|
|||
// Meta
|
||||
local ply = FindMetaTable("Player")
|
||||
|
||||
function ply:gmInteGetTotalMoney()
|
||||
// if darkrp
|
||||
if DarkRP then
|
||||
return self:getDarkRPVar("money")
|
||||
end
|
||||
|
||||
// else
|
||||
return 0
|
||||
end
|
|
@ -1,29 +1,30 @@
|
|||
//
|
||||
// Network
|
||||
// Networking
|
||||
//
|
||||
|
||||
/*
|
||||
Upload
|
||||
1 - Add Chat Message
|
||||
2 - Get Config
|
||||
3 - Test Connection
|
||||
4 - Take Screenshot
|
||||
Receive
|
||||
0 - Player is Ready
|
||||
1 - Test Connection
|
||||
2 - Get Config
|
||||
3 - Set Config
|
||||
4 - Take Screenshot
|
||||
5 - Restart Map
|
||||
*/
|
||||
|
||||
util.AddNetworkString("gmIntegration")
|
||||
|
||||
//
|
||||
// Send Net
|
||||
//
|
||||
|
||||
local netSend = {
|
||||
["wsRelayDiscordChat"] = 1,
|
||||
["adminConfig"] = 2,
|
||||
["testApiConnection"] = 3,
|
||||
["publicConfig"] = 5,
|
||||
["chatColorMessage"] = 6,
|
||||
["openVerifPopup"] = 7,
|
||||
["savePlayerToken"] = 8
|
||||
}
|
||||
|
||||
// Send
|
||||
function gmInte.SendNet(id, data, ply, func)
|
||||
if (!netSend[id]) then return end
|
||||
|
||||
net.Start("gmIntegration")
|
||||
net.WriteUInt(id, 8)
|
||||
net.WriteString(util.TableToJSON(data))
|
||||
net.WriteUInt(netSend[id], 8)
|
||||
net.WriteString(util.TableToJSON(data || {}))
|
||||
if (func) then func() end
|
||||
if (ply == nil) then
|
||||
net.Broadcast()
|
||||
|
@ -32,11 +33,13 @@ function gmInte.SendNet(id, data, ply, func)
|
|||
end
|
||||
end
|
||||
|
||||
// Receive
|
||||
local netFuncs = {
|
||||
//
|
||||
// Receive net
|
||||
//
|
||||
|
||||
local netReceive = {
|
||||
[0] = function(ply)
|
||||
gmInte.userFinishConnect(ply)
|
||||
ply.gmIntTimeConnect = math.Round(RealTime())
|
||||
hook.Run("gmInte:PlayerReady", ply)
|
||||
end,
|
||||
[1] = function(ply, data)
|
||||
gmInte.testConnection(ply, data)
|
||||
|
@ -54,11 +57,21 @@ local netFuncs = {
|
|||
if (!ply:IsSuperAdmin()) then return end
|
||||
RunConsoleCommand("changelevel", game.GetMap())
|
||||
end,
|
||||
[6] = function(ply)
|
||||
gmInte.verifyPlayer(ply)
|
||||
end,
|
||||
[7] = function(ply, data)
|
||||
sendPlayerToken(ply)
|
||||
end
|
||||
}
|
||||
|
||||
net.Receive("gmIntegration", function(len, ply)
|
||||
if !ply:IsPlayer() then return end
|
||||
if (!ply || ply && !ply:IsValid()) then return end
|
||||
|
||||
local id = net.ReadUInt(8)
|
||||
local data = util.JSONToTable(net.ReadString() || "{}")
|
||||
if (netFuncs[id]) then netFuncs[id](ply, data) end
|
||||
|
||||
if (!netReceive[id]) then return end
|
||||
|
||||
netReceive[id](ply, data)
|
||||
end)
|
191
lua/gmod_integration/server/sv_players.lua
Normal file
191
lua/gmod_integration/server/sv_players.lua
Normal file
|
@ -0,0 +1,191 @@
|
|||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
function gmInte.playerReady(ply)
|
||||
if (!ply:IsValid() || !ply:IsPlayer(ply)) then return end
|
||||
|
||||
// Initialize Time
|
||||
ply.gmIntTimeConnect = math.Round(RealTime())
|
||||
|
||||
// Send Public Config
|
||||
gmInte.publicGetConfig(ply)
|
||||
|
||||
gmInte.http.post("/players/" .. ply:SteamID64() .. "/ready", {
|
||||
["player"] = gmInte.getPlayerFormat(ply)
|
||||
})
|
||||
end
|
||||
|
||||
function gmInte.playerConnect(data)
|
||||
data.steamID64 = util.SteamIDTo64(data.networkid)
|
||||
gmInte.http.post("/players/" .. util.SteamIDTo64(data.networkid) .. "/connect", data)
|
||||
end
|
||||
|
||||
function gmInte.playerDisconnected(ply)
|
||||
if (!ply:IsValid() || !ply:IsPlayer(ply)) then return end
|
||||
|
||||
gmInte.http.post("/players/" .. ply:SteamID64() .. "/disconnect",
|
||||
{
|
||||
["player"] = gmInte.getPlayerFormat(ply),
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
-- function gmInte.playerSpawn(ply)
|
||||
-- if (!ply:IsValid() || !ply:IsPlayer(ply)) then return end
|
||||
|
||||
-- gmInte.http.post("/players/" .. ply:SteamID64() .. "/spawn",
|
||||
-- {
|
||||
-- ["player"] = gmInte.getPlayerFormat(ply)
|
||||
-- }
|
||||
-- )
|
||||
-- end
|
||||
|
||||
-- function gmInte.postLogPlayerDeath(ply, inflictor, attacker)
|
||||
-- if (!ply:IsValid() || !ply:IsPlayer(ply)) then return end
|
||||
-- if (!attacker:IsValid() || !attacker:IsPlayer(attacker)) then return end
|
||||
-- if (!inflictor:IsValid()) then return end
|
||||
|
||||
-- gmInte.http.post("/logs/playerDeath",
|
||||
-- {
|
||||
-- ["player"] = gmInte.getPlayerFormat(ply),
|
||||
-- ["inflictor"] = gmInte.getEntityFormat(inflictor),
|
||||
-- ["attacker"] = gmInte.getPlayerFormat(attacker)
|
||||
-- }
|
||||
-- )
|
||||
-- end
|
||||
|
||||
-- function gmInte.postLogPlayerInitialSpawn(ply)
|
||||
-- if (!ply:IsValid() || !ply:IsPlayer(ply)) then return end
|
||||
|
||||
-- gmInte.http.post("/logs/playerInitialSpawn",
|
||||
-- {
|
||||
-- ["ply"] = gmInte.getPlayerFormat(ply)
|
||||
-- }
|
||||
-- )
|
||||
-- end
|
||||
|
||||
-- function gmInte.postLogPlayerHurt(ply, attacker, healthRemaining, damageTaken)
|
||||
-- if (!ply:IsValid() || !ply:IsPlayer(ply)) then return end
|
||||
-- if (!attacker:IsValid() || !attacker:IsPlayer(attacker)) then return end
|
||||
|
||||
-- // Wait a second to see if the player is going to be hurt again
|
||||
-- ply.gmodInteLastHurt = ply.gmodInteLastHurt || {}
|
||||
-- local locCurTime = CurTime()
|
||||
-- ply.gmodInteLastHurt[attacker:SteamID64()] = locCurTime
|
||||
|
||||
-- timer.Simple(1, function()
|
||||
-- if (ply.gmodInteLastHurt[attacker:SteamID64()] != locCurTime) then
|
||||
-- ply.gmodInteTotalDamage = ply.gmodInteTotalDamage || 0
|
||||
-- ply.gmodInteTotalDamage = ply.gmodInteTotalDamage + damageTaken
|
||||
-- return
|
||||
-- end
|
||||
|
||||
-- gmInte.http.post("/logs/playerHurt",
|
||||
-- {
|
||||
-- ["victim"] = gmInte.getPlayerFormat(ply),
|
||||
-- ["attacker"] = gmInte.getPlayerFormat(attacker),
|
||||
-- ["healthRemaining"] = healthRemaining,
|
||||
-- ["damageTaken"] = ply.gmodInteTotalDamage
|
||||
-- }
|
||||
-- )
|
||||
-- end)
|
||||
-- end
|
||||
|
||||
-- function gmInte.postLogPlayerSpawnedSomething(object, ply, ent, model)
|
||||
-- if (!ply:IsValid() || !ply:IsPlayer(ply)) then return end
|
||||
-- if (!ent:IsValid()) then return end
|
||||
|
||||
-- gmInte.http.post("/logs/playerSpawnedSomething",
|
||||
-- {
|
||||
-- ["object"] = object,
|
||||
-- ["player"] = gmInte.getPlayerFormat(ply),
|
||||
-- ["entity"] = gmInte.getEntityFormat(ent),
|
||||
-- ["model"] = model || ""
|
||||
-- }
|
||||
-- )
|
||||
-- end
|
||||
|
||||
-- function gmInte.postLogPlayerGivet(ply, class, swep)
|
||||
-- if (!ply:IsValid() || !ply:IsPlayer(ply)) then return end
|
||||
|
||||
-- gmInte.http.post("/logs/playerGive",
|
||||
-- {
|
||||
-- ["player"] = gmInte.getPlayerFormat(ply),
|
||||
-- ["class"] = class,
|
||||
-- ["swep"] = swep
|
||||
-- }
|
||||
-- )
|
||||
-- end
|
||||
|
||||
|
||||
//
|
||||
// Hooks
|
||||
//
|
||||
|
||||
hook.Add("gmInte:PlayerReady", "gmInte:Player:Ready", function(ply)
|
||||
gmInte.playerReady(ply)
|
||||
end)
|
||||
|
||||
hook.Add("ShutDown", "gmInte:Server:Shutdown:SavePlayers", function()
|
||||
for ply, ply in pairs(player.GetAll()) do
|
||||
gmInte.playerDisconnected(ply)
|
||||
end
|
||||
end)
|
||||
|
||||
gameevent.Listen("player_connect")
|
||||
hook.Add("player_connect", "gmInte:Player:Connect", function(data)
|
||||
gmInte.playerConnect(data)
|
||||
end)
|
||||
|
||||
hook.Add("PlayerDisconnected", "gmInte:Player:Disconnect", function(ply)
|
||||
gmInte.playerDisconnected(ply)
|
||||
end)
|
||||
|
||||
-- hook.Add("PlayerSpawn", "gmInte:Player:Spawn", function(ply)
|
||||
-- gmInte.playerSpawn(ply)
|
||||
-- end)
|
||||
|
||||
-- hook.Add("PlayerInitialSpawn", "gmInte:Player:InitialSpawn", function(ply)
|
||||
-- gmInte.postLogPlayerInitialSpawn(ply)
|
||||
-- end)
|
||||
|
||||
-- hook.Add("PlayerGiveSWEP", "gmInte:Player:SWEPs", function( ply, class, swep )
|
||||
-- gmInte.postLogPlayerGivet(ply, class, swep)
|
||||
-- end)
|
||||
|
||||
-- hook.Add("PlayerDeath", "gmInte:Player:Death", function(ply, inflictor, attacker)
|
||||
-- gmInte.postLogPlayerDeath(ply, inflictor, attacker)
|
||||
-- end)
|
||||
|
||||
-- hook.Add("PlayerHurt", "gmInte:Player:Hurt", function(ply, attacker, healthRemaining, damageTaken)
|
||||
-- gmInte.postLogPlayerHurt(ply, attacker, healthRemaining, damageTaken)
|
||||
-- end)
|
||||
|
||||
-- hook.Add("PlayerSpawnedProp", "gmInte:Player:SpawnedProp", function(ply, model, ent)
|
||||
-- gmInte.postLogPlayerSpawnedSomething("SENT", ply, ent, model)
|
||||
-- end)
|
||||
|
||||
-- hook.Add("PlayerSpawnedSENT", "gmInte:Player:SpawnedSENT", function(ply, ent)
|
||||
-- gmInte.postLogPlayerSpawnedSomething("SENT", ply, ent)
|
||||
-- end)
|
||||
|
||||
-- hook.Add("PlayerSpawnedNPC", "gmInte:Player:SpawnedNPC", function(ply, ent)
|
||||
-- gmInte.postLogPlayerSpawnedSomething("NPC", ply, ent)
|
||||
-- end)
|
||||
|
||||
-- hook.Add("PlayerSpawnedVehicle", "gmInte:Player:SpawnedVehicle", function(ply, ent)
|
||||
-- gmInte.postLogPlayerSpawnedSomething("Vehicle", ply, ent)
|
||||
-- end)
|
||||
|
||||
-- hook.Add("PlayerSpawnedEffect", "gmInte:Player:SpawnedEffect", function(ply, model, ent)
|
||||
-- gmInte.postLogPlayerSpawnedSomething("Effect", ply, ent, model)
|
||||
-- end)
|
||||
|
||||
-- hook.Add("PlayerSpawnedRagdoll", "gmInte:Player:SpawnedRagdoll", function(ply, model, ent)
|
||||
-- gmInte.postLogPlayerSpawnedSomething("Ragdoll", ply, ent, model)
|
||||
-- end)
|
||||
|
||||
-- hook.Add("PlayerSpawnedSWEP", "gmInte:Player:SpawnedSWEP", function(ply, ent)
|
||||
-- gmInte.postLogPlayerSpawnedSomething("SWEP", ply, ent)
|
||||
-- end)
|
42
lua/gmod_integration/server/sv_players_verif.lua
Normal file
42
lua/gmod_integration/server/sv_players_verif.lua
Normal file
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
function gmInte.verifyPlayer(ply)
|
||||
if (!ply:IsValid() || !ply:IsPlayer(ply)) then return end
|
||||
|
||||
gmInte.http.get("/players/" .. ply:SteamID64(), function(code, data)
|
||||
if (!gmInte.config.forcePlayerLink) then return end
|
||||
|
||||
if (data && data.steamID64) then
|
||||
if (ply.gmIntVerified) then return end
|
||||
gmInte.SendNet("chatColorMessage", {
|
||||
[1] = {
|
||||
["text"] = "You have been verified",
|
||||
["color"] = Color(255, 255, 255)
|
||||
}
|
||||
}, ply)
|
||||
ply:Freeze(false)
|
||||
ply.gmIntVerified = true
|
||||
else
|
||||
gmInte.SendNet("chatColorMessage", {
|
||||
[1] = {
|
||||
["text"] = "You are not verified",
|
||||
["color"] = Color(255, 0, 0)
|
||||
}
|
||||
}, ply)
|
||||
ply:Freeze(true)
|
||||
gmInte.SendNet("openVerifPopup", nil, ply)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
//
|
||||
// Hooks
|
||||
//
|
||||
|
||||
hook.Add("gmInte:PlayerReady", "gmInte:Verif:PlayerReady", function(ply)
|
||||
if (!gmInte.config.forcePlayerLink) then return end
|
||||
|
||||
gmInte.verifyPlayer(ply)
|
||||
end)
|
8
lua/gmod_integration/server/sv_rcon.lua
Normal file
8
lua/gmod_integration/server/sv_rcon.lua
Normal file
|
@ -0,0 +1,8 @@
|
|||
//
|
||||
// Websocket
|
||||
//
|
||||
|
||||
function gmInte.wsRcon(data)
|
||||
gmInte.log("Rcon Command from Discord '" .. data.command .. "' by " .. data.steamID)
|
||||
game.ConsoleCommand(data.command .. "\n")
|
||||
end
|
84
lua/gmod_integration/server/sv_settings.lua
Normal file
84
lua/gmod_integration/server/sv_settings.lua
Normal file
|
@ -0,0 +1,84 @@
|
|||
function gmInte.saveSetting(setting, value)
|
||||
if gmInte.config[setting] == nil then
|
||||
gmInte.log("Unknown Setting")
|
||||
return
|
||||
end
|
||||
|
||||
// Boolean
|
||||
if (value == "true") then value = true end
|
||||
if (value == "false") then value = false end
|
||||
|
||||
// Number
|
||||
if (tonumber(value) != nil) then value = tonumber(value) end
|
||||
|
||||
gmInte.config[setting] = value
|
||||
file.Write("gm_integration/config.json", util.TableToJSON(gmInte.config, true))
|
||||
gmInte.log("Setting Saved")
|
||||
|
||||
// send to all players if it's a public setting
|
||||
for _, ply in pairs(player.GetAll()) do
|
||||
if (ply:IsValid() && ply:IsPlayer(ply)) then
|
||||
gmInte.log("Sending new Public Config to " .. ply:Nick())
|
||||
gmInte.publicGetConfig(ply)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function gmInte.tryConfig()
|
||||
gmInte.http.get("",
|
||||
function(code, body)
|
||||
print(" ")
|
||||
gmInte.log("Congratulations your server is now connected to Gmod Integration")
|
||||
gmInte.log("Server Name: " .. body.name)
|
||||
gmInte.log("Server ID: " .. body.id)
|
||||
print(" ")
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
function gmInte.testConnection(ply)
|
||||
gmInte.http.get("",
|
||||
function(code, body)
|
||||
if (ply) then gmInte.SendNet("testApiConnection", body, ply) end
|
||||
end,
|
||||
function(code, body)
|
||||
if (ply) then gmInte.SendNet("testApiConnection", body, ply) end
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
function gmInte.refreshSettings()
|
||||
gmInte.config = util.JSONToTable(file.Read("gm_integration/config.json", "DATA"))
|
||||
gmInte.log("Settings Refreshed")
|
||||
gmInte.tryConfig()
|
||||
end
|
||||
|
||||
function gmInte.superadminGetConfig(ply)
|
||||
if (!ply:IsValid() || !ply:IsPlayer(ply) || !ply:IsSuperAdmin()) then return end
|
||||
|
||||
gmInte.config.websocket = GWSockets && true || false
|
||||
gmInte.SendNet("adminConfig", gmInte.config, ply)
|
||||
end
|
||||
|
||||
function gmInte.publicGetConfig(ply)
|
||||
if (!ply:IsValid() || !ply:IsPlayer(ply)) then return end
|
||||
|
||||
gmInte.SendNet("publicConfig", {
|
||||
["id"] = gmInte.config.id,
|
||||
["debug"] = gmInte.config.debug,
|
||||
["apiFQDN"] = gmInte.config.apiFQDN,
|
||||
["websocketFQDN"] = gmInte.config.websocketFQDN,
|
||||
}, ply)
|
||||
end
|
||||
|
||||
function gmInte.superadminSetConfig(ply, data)
|
||||
if (!ply:IsValid() || !ply:IsPlayer(ply) || !ply:IsSuperAdmin()) then return end
|
||||
|
||||
for k, v in pairs(data) do
|
||||
gmInte.saveSetting(k, v)
|
||||
end
|
||||
|
||||
if data.token || data.id then
|
||||
gmInte.testConnection(ply)
|
||||
end
|
||||
end
|
38
lua/gmod_integration/server/sv_status.lua
Normal file
38
lua/gmod_integration/server/sv_status.lua
Normal file
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
function gmInte.sendStatus()
|
||||
gmInte.http.post("/status", gmInte.getServerFormat())
|
||||
end
|
||||
|
||||
-- function gmInte.serverStart()
|
||||
-- gmInte.http.post("/start", gmInte.getServerFormat())
|
||||
-- end
|
||||
|
||||
function gmInte.serverShutDown()
|
||||
gmInte.http.post("/shutdown")
|
||||
end
|
||||
|
||||
//
|
||||
// Timers
|
||||
//
|
||||
|
||||
timer.Create("gmInte.sendStatus", 300, 0, function()
|
||||
gmInte.sendStatus()
|
||||
end)
|
||||
|
||||
//
|
||||
// Hooks
|
||||
//
|
||||
|
||||
hook.Add("Initialize", "gmInte:Server:Initialize:SendStatus", function()
|
||||
timer.Simple(1, function()
|
||||
-- gmInte.serverStart()
|
||||
gmInte.sendStatus()
|
||||
end)
|
||||
end)
|
||||
|
||||
hook.Add("ShutDown", "gmInte:Server:ShutDown:SendStatus", function()
|
||||
gmInte.serverShutDown()
|
||||
end)
|
29
lua/gmod_integration/server/sv_sync_bans.lua
Normal file
29
lua/gmod_integration/server/sv_sync_bans.lua
Normal file
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// Websocket
|
||||
//
|
||||
|
||||
function gmInte.wsSyncBan(data)
|
||||
for _, ply in ipairs(player.GetAll()) do
|
||||
if (ply:SteamID64() == data.steam) then
|
||||
ply:Kick(data.reason || "You have been banned from the server.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
function gmInte.playerBan(data)
|
||||
data.steamID64 = util.SteamIDTo64(data.networkid)
|
||||
gmInte.http.post("/players/" .. util.SteamIDTo64(data.networkid) .. "/ban", data)
|
||||
end
|
||||
|
||||
//
|
||||
// Hooks
|
||||
//
|
||||
|
||||
gameevent.Listen("server_addban")
|
||||
hook.Add("server_addban", "gmInte:Player:Ban", function(data)
|
||||
gmInte.playerBan(data)
|
||||
end)
|
31
lua/gmod_integration/server/sv_sync_chat.lua
Normal file
31
lua/gmod_integration/server/sv_sync_chat.lua
Normal file
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// Websocket
|
||||
//
|
||||
|
||||
function gmInte.wsPlayerSay(data)
|
||||
gmInte.SendNet("wsRelayDiscordChat", data, nil)
|
||||
end
|
||||
|
||||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
function gmInte.playerSay(ply, text, teamOnly)
|
||||
if (!gmInte.config.syncChat) then return end
|
||||
|
||||
gmInte.http.post("/players/" .. ply:SteamID64() .. "/say",
|
||||
{
|
||||
["player"] = gmInte.getPlayerFormat(ply),
|
||||
["text"] = text,
|
||||
["teamOnly"] = teamOnly,
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
//
|
||||
// Hooks
|
||||
//
|
||||
|
||||
hook.Add("PlayerSay", "gmInte:SyncChat:PlayerSay", function(ply, text, team)
|
||||
gmInte.playerSay(ply, text, team)
|
||||
end)
|
30
lua/gmod_integration/server/sv_sync_kicks.lua
Normal file
30
lua/gmod_integration/server/sv_sync_kicks.lua
Normal file
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// Websocket
|
||||
//
|
||||
|
||||
function gmInte.wsSyncKick(data)
|
||||
for _, ply in ipairs(player.GetAll()) do
|
||||
if (ply:SteamID64() == data.steam) then
|
||||
ply:Kick(data.reason || "You have been banned from the server.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
function gmInte.playerKick(data)
|
||||
gmInte.http.post("/players/" .. util.SteamIDTo64(data.networkid) .. "/kick", data)
|
||||
end
|
||||
|
||||
//
|
||||
// Hooks
|
||||
//
|
||||
|
||||
gameevent.Listen("player_disconnect")
|
||||
hook.Add("player_disconnect", "gmInte:SyncKick:Disconnect", function(data)
|
||||
if (string.StartWith(data.reason, "Kicked by ") || data.reason == "No reason provided.") then
|
||||
gmInte.playerKick(data)
|
||||
end
|
||||
end)
|
33
lua/gmod_integration/server/sv_sync_names.lua
Normal file
33
lua/gmod_integration/server/sv_sync_names.lua
Normal file
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// Websocket
|
||||
//
|
||||
|
||||
function gmInte.wsSyncName(data)
|
||||
local ply = player.GetBySteamID(data.player.steamID64)
|
||||
if not IsValid(ply) then return end
|
||||
ply:SetName(data.newName)
|
||||
end
|
||||
|
||||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
function gmInte.playerChangeName(ply, oldName, newName)
|
||||
if (!ply:IsValid() || !ply:IsPlayer(ply)) then return end
|
||||
|
||||
gmInte.http.post("/players/" .. ply:SteamID64() .. "/name",
|
||||
{
|
||||
["player"] = gmInte.getPlayerFormat(ply),
|
||||
["oldName"] = oldName,
|
||||
["newName"] = newName,
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
//
|
||||
// Hooks
|
||||
//
|
||||
|
||||
hook.Add("onPlayerChangedName", "gmInte:PlayerChangeName", function(ply, old, new)
|
||||
gmInte.playerChangeName(ply, old, new)
|
||||
end)
|
101
lua/gmod_integration/server/sv_sync_roles.lua
Normal file
101
lua/gmod_integration/server/sv_sync_roles.lua
Normal file
|
@ -0,0 +1,101 @@
|
|||
//
|
||||
// Websocket
|
||||
//
|
||||
|
||||
local cachedPlayers = {}
|
||||
|
||||
function gmInte.wsPlayerUpdateGroup(data)
|
||||
if (cachedPlayers[steamID64] == data.group) then return end
|
||||
|
||||
data.steamID = util.SteamIDFrom64(data.steamID64)
|
||||
data.group = data.add && data.group || "user"
|
||||
|
||||
cachedPlayers[data.steamID64] = data.group
|
||||
|
||||
local ply = player.GetBySteamID(data.steamID)
|
||||
if (ply && ply:IsValid()) then
|
||||
ply:SetUserGroup(data.group)
|
||||
end
|
||||
|
||||
// ULX
|
||||
if (ULib) then
|
||||
ULib.ucl.addUser(data.steamID, nil, nil, data.group)
|
||||
end
|
||||
|
||||
// ServerGuard
|
||||
if (serverguard) then
|
||||
local ply = player.GetBySteamID(data.steamID)
|
||||
if (ply) then
|
||||
local rankData = serverguard.ranks:GetRank(data.group)
|
||||
serverguard.player:SetRank(ply, data.group)
|
||||
serverguard.player:SetImmunity(ply, rankData.immunity)
|
||||
serverguard.player:SetTargetableRank(ply, rankData.targetable)
|
||||
serverguard.player:SetBanLimit(ply, rankData.banlimit)
|
||||
else
|
||||
serverguard.player:SetRank(data.steamID, data.group)
|
||||
end
|
||||
end
|
||||
|
||||
// Evolve
|
||||
if (evolve) then
|
||||
evolve:RankPlayer(data.steamID64, data.group)
|
||||
end
|
||||
|
||||
// SAM
|
||||
if (SAM) then
|
||||
SAM:PlayerSetRank(data.steamID64, data.group)
|
||||
end
|
||||
|
||||
// sam (wtf another one?)
|
||||
if (sam) then
|
||||
sam.player.setRank(data.steamID64, data.group)
|
||||
end
|
||||
|
||||
// xAdmin
|
||||
if (xAdmin) then
|
||||
xAdmin.SetRank(data.steamID64, data.group)
|
||||
end
|
||||
|
||||
// maestro
|
||||
if (maestro) then
|
||||
maestro.userrank(data.steamID64, data.group)
|
||||
end
|
||||
|
||||
// D3A
|
||||
if (D3A) then
|
||||
D3A.Ranks.SetSteamIDRank(data.steamID, data.group)
|
||||
end
|
||||
|
||||
// Mercury
|
||||
if (Mercury) then
|
||||
RunConsoleCommand("hg", "setrank", data.steamID, data.group)
|
||||
end
|
||||
|
||||
// FAdmin
|
||||
if (FAdmin) then
|
||||
RunConsoleCommand("fadmin", "setaccess", data.steamID, data.group)
|
||||
end
|
||||
|
||||
gmInte.log("[Sync Role] Player " .. data.steamID .. " has been updated to group " .. data.group)
|
||||
end
|
||||
|
||||
function gmInte.playerChangeGroup(steamID64, oldGroup, newGroup)
|
||||
if (cachedPlayers[steamID64] == newGroup) then return end
|
||||
cachedPlayers[steamID64] = newGroup
|
||||
|
||||
gmInte.http.post("/players/" .. steamID64 .. "/group", {
|
||||
["player"] = gmInte.getPlayerFormat(ply),
|
||||
["oldGroup"] = oldGroup || "user",
|
||||
["newGroup"] = newGroup
|
||||
})
|
||||
end
|
||||
|
||||
hook.Add('CAMI.PlayerUsergroupChanged', 'gmInte:SyncChat:CAMI:PlayerUsergroupChanged', function(ply, old, new)
|
||||
if (ply:IsBot() || !ply:IsValid()) then return end
|
||||
gmInte.playerChangeGroup(ply:SteamID64(), old, new)
|
||||
end)
|
||||
|
||||
hook.Add('CAMI.SteamIDUsergroupChanged', 'gmInte:SyncChat:CAMI:SteamIDUsergroupChanged', function(SteamID64, old, new)
|
||||
if (string.StartWith(SteamID64, "STEAM_")) then SteamID64 = util.SteamIDTo64(SteamID64) end
|
||||
gmInte.playerChangeGroup(SteamID64, old, new)
|
||||
end)
|
50
lua/gmod_integration/server/sv_tokens.lua
Normal file
50
lua/gmod_integration/server/sv_tokens.lua
Normal file
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
gmInte.serverPublicToken = gmInte.serverPublicToken || nil
|
||||
function gmInte.getPublicServerToken(callback)
|
||||
if (gmInte.serverPublicToken) then
|
||||
if (callback) then callback(gmInte.serverPublicToken) end
|
||||
return
|
||||
end
|
||||
|
||||
gmInte.http.get("/public-token", function(code, data)
|
||||
gmInte.serverPublicToken = data.publicTempToken
|
||||
callback(data.publicTempToken)
|
||||
end)
|
||||
end
|
||||
|
||||
hook.Add("Initialize", "gmInte:Server:Initialize:GetPublicToken", function()
|
||||
timer.Simple(1, function()
|
||||
gmInte.getPublicServerToken(function(publicToken)
|
||||
gmInte.log("Server Public Token Received: " .. publicToken)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
gmInte.serverPlayerTempTokens = gmInte.serverPlayerTempTokens || {}
|
||||
function gmInte.getPlayerTempToken(ply, callback)
|
||||
if (gmInte.serverPlayerTempTokens[ply:SteamID64()] && gmInte.serverPlayerTempTokens[ply:SteamID64()].userID == ply:UserID()) then
|
||||
if (callback) then callback(gmInte.serverPlayerTempTokens[ply:SteamID64()].token) end
|
||||
return
|
||||
end
|
||||
|
||||
gmInte.getPublicServerToken(function(publicToken)
|
||||
local token = util.SHA256(ply:SteamID64() .. "-" .. publicToken .. "-" .. gmInte.config.token .. "-" .. ply:UserID()) .. " " .. ply:UserID()
|
||||
gmInte.serverPlayerTempTokens[ply:SteamID64()] = { token = token, userID = ply:UserID() }
|
||||
callback(token)
|
||||
end)
|
||||
end
|
||||
|
||||
function sendPlayerToken(ply)
|
||||
gmInte.getPlayerTempToken(ply, function(token)
|
||||
gmInte.SendNet("savePlayerToken", {
|
||||
token = token,
|
||||
}, ply)
|
||||
end)
|
||||
end
|
||||
|
||||
hook.Add("gmInte:PlayerReady", "gmInte:Verif:PlayerReady", function(ply)
|
||||
sendPlayerToken(ply)
|
||||
end)
|
74
lua/gmod_integration/shared/sh_api_format.lua
Normal file
74
lua/gmod_integration/shared/sh_api_format.lua
Normal file
|
@ -0,0 +1,74 @@
|
|||
function gmInte.getPlayerFormat(ply)
|
||||
if (!IsValid(ply) || !ply:IsPlayer()) then return end
|
||||
return {
|
||||
["steamID"] = ply:SteamID(),
|
||||
["steamID64"] = ply:SteamID64(),
|
||||
["userGroup"] = ply:GetUserGroup(),
|
||||
["team"] = gmInte.getTeamFormat(ply:Team()),
|
||||
["name"] = ply:Nick(),
|
||||
["kills"] = ply:Frags(),
|
||||
["deaths"] = ply:Deaths(),
|
||||
["customValues"] = ply:gmIntGetCustomValues(),
|
||||
["connectTime"] = math.Round(RealTime() - ply:gmIntGetConnectTime()),
|
||||
["ping"] = ply:Ping(),
|
||||
["position"] = gmInte.getVectorFormat(ply:GetPos()),
|
||||
["angle"] = gmInte.getAngleFormat(ply:EyeAngles())
|
||||
}
|
||||
end
|
||||
|
||||
function gmInte.getServerFormat()
|
||||
return {
|
||||
["hostname"] = GetHostName(),
|
||||
["ip"] = game.GetIPAddress(),
|
||||
["port"] = GetConVar("hostport"):GetInt(),
|
||||
["map"] = game.GetMap(),
|
||||
["players"] = #player.GetAll(),
|
||||
["maxPlayers"] = game.MaxPlayers(),
|
||||
["gameMode"] = engine.ActiveGamemode(),
|
||||
["uptime"] = math.Round(RealTime())
|
||||
}
|
||||
end
|
||||
|
||||
function gmInte.getWeaponFormat(weapon)
|
||||
if (!IsValid(weapon) || !weapon:IsWeapon()) then return end
|
||||
return {
|
||||
["class"] = weapon:GetClass(),
|
||||
["printName"] = weapon:GetPrintName()
|
||||
}
|
||||
end
|
||||
|
||||
function gmInte.getEntityFormat(ent)
|
||||
if (!IsValid(ent)) then return end
|
||||
return {
|
||||
["class"] = ent:GetClass(),
|
||||
["model"] = ent:GetModel(),
|
||||
["position"] = gmInte.getVectorFormat(ent:GetPos()),
|
||||
["angle"] = gmInte.getAngleFormat(ent:GetAngles())
|
||||
}
|
||||
end
|
||||
|
||||
function gmInte.getVectorFormat(vec)
|
||||
if (!isvector(vec)) then return end
|
||||
return {
|
||||
["x"] = vec.x,
|
||||
["y"] = vec.y,
|
||||
["z"] = vec.z
|
||||
}
|
||||
end
|
||||
|
||||
function gmInte.getAngleFormat(ang)
|
||||
if (!isangle(ang)) then return end
|
||||
return {
|
||||
["p"] = ang.p,
|
||||
["y"] = ang.y,
|
||||
["r"] = ang.r
|
||||
}
|
||||
end
|
||||
|
||||
function gmInte.getTeamFormat(teamID)
|
||||
if (!isnumber(teamID)) then return end
|
||||
return {
|
||||
["id"] = teamID,
|
||||
["name"] = team.GetName(teamID)
|
||||
}
|
||||
end
|
39
lua/gmod_integration/shared/sh_errors.lua
Normal file
39
lua/gmod_integration/shared/sh_errors.lua
Normal file
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
function gmInte.sendLuaErrorReport(err, realm, stack, name, id, uptime)
|
||||
if (name != "gmod_integration") then return end
|
||||
|
||||
if (SERVER && math.Round(RealTime()) == 0) then
|
||||
return timer.Simple(1, function()
|
||||
gmInte.sendLuaErrorReport(err, realm, stack, name, id, math.Round(RealTime()))
|
||||
end)
|
||||
end
|
||||
|
||||
if (CLIENT && (!IsValid(LocalPlayer()) || !gmInte.config.token)) then
|
||||
return timer.Simple(1, function()
|
||||
gmInte.sendLuaErrorReport(err, realm, stack, name, id, math.Round(RealTime()))
|
||||
end)
|
||||
end
|
||||
|
||||
gmInte.http.post("/errors",
|
||||
{
|
||||
["error"] = err,
|
||||
["realm"] = realm,
|
||||
["stack"] = stack,
|
||||
["name"] = name,
|
||||
["id"] = id,
|
||||
["uptime"] = uptime || math.Round(RealTime()),
|
||||
["identifier"] = SERVER && gmInte.config.id || LocalPlayer():SteamID64()
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
//
|
||||
// Hooks
|
||||
//
|
||||
|
||||
hook.Add("OnLuaError", "gmInte:OnLuaError:SendReport", function(err, realm, stack, name, id)
|
||||
gmInte.sendLuaErrorReport(err, realm, stack, name, id)
|
||||
end)
|
|
@ -1,126 +1,144 @@
|
|||
local apiVersion = "v3"
|
||||
gmInte.http = gmInte.http || {}
|
||||
|
||||
//
|
||||
// HTTP
|
||||
//
|
||||
|
||||
local failMessage = {
|
||||
["401"] = "Bad Credentials",
|
||||
["403"] = "Forbidden",
|
||||
["404"] = "Not Found",
|
||||
["500"] = "Internal Server Error",
|
||||
["503"] = "Service Unavailable",
|
||||
["504"] = "Gateway Timeout",
|
||||
}
|
||||
local function getAPIURL(endpoint)
|
||||
local url = "https://" .. gmInte.config.apiFQDN .. "/" .. apiVersion
|
||||
|
||||
local function errorMessage(body, code)
|
||||
if (body && body.error) then
|
||||
if (failMessage[code]) then
|
||||
return failMessage[code]
|
||||
else
|
||||
return body.error
|
||||
end
|
||||
elseif (failMessage[code]) then
|
||||
return failMessage[code]
|
||||
if (SERVER) then
|
||||
url = url .. "/servers/" .. gmInte.config.id
|
||||
else
|
||||
return code
|
||||
end
|
||||
end
|
||||
if (string.sub(endpoint, 1, 8) == "/users") then
|
||||
return url .. endpoint
|
||||
end
|
||||
|
||||
local function getAPIURL()
|
||||
local url = "https://api.gmod-integration.com"
|
||||
local devURL = "https://dev-api.gmod-integration.com"
|
||||
|
||||
if (!gmInte.config.debug) then return url end
|
||||
if (gmInte.config.devInstance) then
|
||||
gmInte.log("Using dev Instance", true)
|
||||
return devURL
|
||||
url = url .. "/clients/" .. LocalPlayer():SteamID64() .. "/servers/" .. gmInte.config.id
|
||||
end
|
||||
|
||||
return url
|
||||
return url .. endpoint
|
||||
end
|
||||
|
||||
local function sendHTTP(params)
|
||||
// Log the HTTP request
|
||||
gmInte.log("HTTP Request: " .. params.method .. " " .. params.endpoint, true)
|
||||
gmInte.log("HTTP Body: " .. (params.body || "No body"), true)
|
||||
local function showableBody(endpoint)
|
||||
// if start with /streams or /screenshots return false
|
||||
if (string.sub(endpoint, 1, 8) == "/streams" || string.sub(endpoint, 1, 12) == "/screenshots") then
|
||||
return false
|
||||
end
|
||||
|
||||
// Send the HTTP request
|
||||
return true
|
||||
end
|
||||
|
||||
local function genRequestID()
|
||||
return "gmInte-" .. util.CRC(tostring(SysTime()))
|
||||
end
|
||||
|
||||
function gmInte.http.requestAPI(params)
|
||||
local body = params.body && util.TableToJSON(params.body || {}) || ""
|
||||
local bodyLength = string.len(body)
|
||||
local token = params.token || gmInte.config.token || ""
|
||||
local url = getAPIURL(params.endpoint)
|
||||
local method = params.method
|
||||
local success = params.success || function() end
|
||||
local failed = params.failed || function() if (!gmInte.config.debug) then gmInte.log("HTTP Failed, if this error persists please contact support") end end
|
||||
local version = gmInte.config.version
|
||||
local showableBody = showableBody(params.endpoint)
|
||||
local requestID = genRequestID()
|
||||
|
||||
local headers = {
|
||||
["Content-Type"] = "application/json",
|
||||
["Content-Length"] = bodyLength,
|
||||
["Authorization"] = "Bearer " .. token,
|
||||
["Version"] = version
|
||||
}
|
||||
local type = "application/json"
|
||||
|
||||
// Log
|
||||
gmInte.log("HTTP FQDN: " .. gmInte.config.apiFQDN, true)
|
||||
gmInte.log("HTTP Request ID: " .. requestID, true)
|
||||
gmInte.log("HTTP Request: " .. method .. " " .. url, true)
|
||||
gmInte.log("HTTP Body: " .. (showableBody && body || "HIDDEN"), true)
|
||||
|
||||
// Send
|
||||
HTTP({
|
||||
url = getAPIURL() .. params.endpoint,
|
||||
method = params.method,
|
||||
headers = {
|
||||
["Content-Type"] = "application/json",
|
||||
["Content-Length"] = params.body && string.len(params.body) || 0,
|
||||
["id"] = gmInte.config.id,
|
||||
["token"] = gmInte.config.token,
|
||||
["version"] = gmInte.version
|
||||
},
|
||||
body = params.body && params.body || "",
|
||||
type = "application/json",
|
||||
success = function(code, body, headers)
|
||||
// Log the HTTP response
|
||||
["url"] = url,
|
||||
["method"] = method,
|
||||
["headers"] = headers,
|
||||
["body"] = body,
|
||||
["type"] = type,
|
||||
["success"] = function(code, body, headers)
|
||||
// Log
|
||||
gmInte.log("HTTP Request ID: " .. requestID, true)
|
||||
gmInte.log("HTTP Response: " .. code, true)
|
||||
if (gmInte.config.debug) then gmInte.log("HTTP Body: " .. body, true) end
|
||||
|
||||
// if body and is json extract it
|
||||
if (body && string.sub(headers["Content-Type"], 1, 16) == "application/json") then
|
||||
body = util.JSONToTable(body)
|
||||
// if not application/json return failed
|
||||
if (string.sub(headers["Content-Type"], 1, 16) != "application/json") then
|
||||
gmInte.log("HTTP Failed: Invalid Content-Type", true)
|
||||
return failed({ ["error"] = "Invalid Content-Type" }, code, headers)
|
||||
end
|
||||
|
||||
// Check if the request was successful
|
||||
if (string.sub(code, 1, 1) == "2") then
|
||||
if (params.success) then
|
||||
params.success(code, body, headers)
|
||||
else
|
||||
gmInte.log("HTTP Request Successful", true)
|
||||
end
|
||||
else
|
||||
if (params.failed) then
|
||||
params.failed(code, body, headers)
|
||||
else
|
||||
gmInte.logError(errorMessage(body, code))
|
||||
end
|
||||
// Parse body
|
||||
body = util.JSONToTable(body || "{}")
|
||||
|
||||
// if not 2xx return failed
|
||||
if (code < 200 || code >= 300) then
|
||||
return failed(code, body, headers)
|
||||
end
|
||||
|
||||
// Return success
|
||||
return success(code, body)
|
||||
end,
|
||||
failed = function(error)
|
||||
gmInte.logError(error)
|
||||
["failed"] = function(error)
|
||||
// Log
|
||||
gmInte.log("HTTP Request ID: " .. requestID, true)
|
||||
gmInte.log("HTTP Failed: " .. error, true)
|
||||
|
||||
// Return failed
|
||||
return failed({ ["error"] = error })
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
function gmInte.get(endpoint, onSuccess, onFailed)
|
||||
sendHTTP({
|
||||
endpoint = endpoint,
|
||||
method = "GET",
|
||||
success = onSuccess,
|
||||
failed = onFailed
|
||||
//
|
||||
// HTTP Methods
|
||||
//
|
||||
|
||||
function gmInte.http.get(endpoint, onSuccess, onFailed)
|
||||
gmInte.http.requestAPI({
|
||||
["endpoint"] = endpoint,
|
||||
["method"] = "GET",
|
||||
["success"] = onSuccess,
|
||||
["failed"] = onFailed
|
||||
})
|
||||
end
|
||||
|
||||
function gmInte.post(endpoint, data, onSuccess, onFailed)
|
||||
sendHTTP({
|
||||
endpoint = endpoint,
|
||||
method = "POST",
|
||||
body = util.TableToJSON(data),
|
||||
success = onSuccess,
|
||||
failed = onFailed
|
||||
function gmInte.http.post(endpoint, data, onSuccess, onFailed)
|
||||
gmInte.http.requestAPI({
|
||||
["endpoint"] = endpoint,
|
||||
["method"] = "POST",
|
||||
["body"] = data,
|
||||
["success"] = onSuccess,
|
||||
["failed"] = onFailed
|
||||
})
|
||||
end
|
||||
|
||||
function gmInte.put(endpoint, data, onSuccess, onFailed)
|
||||
sendHTTP({
|
||||
endpoint = endpoint,
|
||||
method = "PUT",
|
||||
body = util.TableToJSON(data),
|
||||
success = onSuccess,
|
||||
failed = onFailed
|
||||
function gmInte.http.put(endpoint, data, onSuccess, onFailed)
|
||||
gmInte.http.requestAPI({
|
||||
["endpoint"] = endpoint,
|
||||
["method"] = "PUT",
|
||||
["body"] = data,
|
||||
["success"] = onSuccess,
|
||||
["failed"] = onFailed
|
||||
})
|
||||
end
|
||||
|
||||
function gmInte.delete(endpoint, onSuccess, onFailed)
|
||||
sendHTTP({
|
||||
endpoint = endpoint,
|
||||
method = "DELETE",
|
||||
success = onSuccess,
|
||||
failed = onFailed
|
||||
function gmInte.http.delete(endpoint, onSuccess, onFailed)
|
||||
gmInte.http.requestAPI({
|
||||
["endpoint"] = endpoint,
|
||||
["method"] = "DELETE",
|
||||
["success"] = onSuccess,
|
||||
["failed"] = onFailed
|
||||
})
|
||||
end
|
72
lua/gmod_integration/shared/sh_player_meta.lua
Normal file
72
lua/gmod_integration/shared/sh_player_meta.lua
Normal file
|
@ -0,0 +1,72 @@
|
|||
//
|
||||
// Meta
|
||||
//
|
||||
|
||||
local ply = FindMetaTable("Player")
|
||||
|
||||
function ply:gmIntGetConnectTime()
|
||||
return self.gmIntTimeConnect || 0
|
||||
end
|
||||
|
||||
function ply:gmIntSetCustomValue(key, value)
|
||||
self.gmIntCustomValues = self.gmIntCustomValues || {}
|
||||
self.gmIntCustomValues[key] = value
|
||||
end
|
||||
|
||||
function ply:gmIntGetCustomValue(key)
|
||||
return self.gmIntCustomValues && self.gmIntCustomValues[key]
|
||||
end
|
||||
|
||||
function ply:gmIntRemoveCustomValue(key)
|
||||
if (self.gmIntCustomValues) then
|
||||
self.gmIntCustomValues[key] = nil
|
||||
end
|
||||
end
|
||||
|
||||
//
|
||||
// Compatibility
|
||||
//
|
||||
|
||||
local function getCustomCompatability(ply)
|
||||
local values = {}
|
||||
|
||||
// DarkRP
|
||||
if (DarkRP) then
|
||||
values.money = ply:getDarkRPVar("money")
|
||||
values.job = ply:getDarkRPVar("job")
|
||||
end
|
||||
|
||||
// GUI Level System
|
||||
if (GUILevelSystem) then
|
||||
values.level = ply:GetLevel()
|
||||
values.xp = ply:GetXP()
|
||||
end
|
||||
|
||||
return values
|
||||
end
|
||||
|
||||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
local function getCustomValues(ply)
|
||||
local values = {}
|
||||
|
||||
// Get compatability values
|
||||
for key, value in pairs(getCustomCompatability(ply)) do
|
||||
values[key] = value
|
||||
end
|
||||
|
||||
// Get custom values or overwrite compatability values
|
||||
if (ply.gmIntCustomValues) then
|
||||
for key, value in pairs(ply.gmIntCustomValues) do
|
||||
values[key] = value
|
||||
end
|
||||
end
|
||||
|
||||
return values
|
||||
end
|
||||
|
||||
function ply:gmIntGetCustomValues()
|
||||
return getCustomValues(self)
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Informations:
|
||||
This file is prioritized over the configuration file in data/gmod-integration/config.json until the id are set.
|
||||
This file is prioritized over the configuration file in data/gmod-integration/config.json if id and token are set in this file.
|
||||
We don't recommend to use a static version of our addon, you should use the workshop version instead.
|
||||
|
||||
Add Server:
|
||||
|
@ -25,50 +25,31 @@
|
|||
// API Connection
|
||||
gmInte.config.id = "" // Server ID
|
||||
gmInte.config.token = "" // Server Token
|
||||
|
||||
// Websocket
|
||||
/*
|
||||
This is a premium feature, you can buy premium on our website: https://gmod-integration.com/premium
|
||||
Websocket allow you to made a real-time connection between your server and our servers.
|
||||
And so use the real-time features of our addon (like the chat syncronization, role syncronization, ...)
|
||||
*/
|
||||
gmInte.config.websocket = false // If true, the addon will use the websocket instead of the http requests
|
||||
gmInte.config.websocketFQDN = "ws.gmod-integration.com" // The FQDN of the websocket server
|
||||
gmInte.config.apiFQDN = "api.gmod-integration.com" // The FQDN of the API server
|
||||
|
||||
// Other
|
||||
gmInte.config.forcePlayerLink = false // If true, the addon will force the players to link their discord account to their steam account before playing
|
||||
gmInte.config.supportLink = "" // The link of your support (shown when a player do not have the requiments to join the server)
|
||||
gmInte.config.logBotActions = false // If true, the addon will log the messages of the bot in the console
|
||||
gmInte.config.maintenance = false // If true, the addon will only allow the players with the "gmod-integration.maintenance" permission to join the server
|
||||
|
||||
//
|
||||
// Syncronization
|
||||
//
|
||||
|
||||
// General
|
||||
gmInte.config.syncChat = false // If true, the addon will sync the chat gmod with a selected channel on discord (need to be enabled on the dashboard)
|
||||
gmInte.config.syncPlayerStat = true // If true, the addon will sync the player stats (kills, deaths, playtime, ...)
|
||||
|
||||
// Punishment
|
||||
gmInte.config.syncBan = true // If true, the addon will sync gmod bans with discord bans (and vice versa)
|
||||
gmInte.config.syncTimeout = false // If true, the addon will sync gmod timeouts with discord timeouts (and vice versa)
|
||||
gmInte.config.syncKick = false // If true, the addon will sync gmod kicks with discord kicks (and vice versa)
|
||||
|
||||
//
|
||||
// Player Filter
|
||||
//
|
||||
|
||||
// Trust Factor
|
||||
gmInte.config.minimalTrust = 30 // The minimal trust factor of an user to be able to join the server (0 to 100)
|
||||
gmInte.config.filterOnTrust = true // If true, the addon will filter the players according to their trust factor
|
||||
|
||||
// Ban
|
||||
gmInte.config.filterOnBan = true // If true, the addon will filter the players according to their ban status
|
||||
|
||||
//
|
||||
// Features Kill Switch
|
||||
// Materials
|
||||
//
|
||||
|
||||
// Will disable the features of the addon
|
||||
gmInte.config.sendLog = false // Disable the logs
|
||||
gmInte.config.redownloadMaterials = false // If true, the addon will redownload the materials of the addon (useful if you have a problem with the materials)
|
||||
|
||||
//
|
||||
// Debug & Development
|
||||
|
|
Loading…
Reference in New Issue
Block a user