diff --git a/lua/gmod_integration/client/cl_gui.lua b/lua/gmod_integration/client/cl_gui.lua index c12610f..638e24d 100644 --- a/lua/gmod_integration/client/cl_gui.lua +++ b/lua/gmod_integration/client/cl_gui.lua @@ -1,5 +1,5 @@ local function saveConfig(setting, value) - gmInte.SendNet("3", { + gmInte.SendNet(3, { [setting] = value }) end @@ -104,6 +104,7 @@ local possibleConfig = { ["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 @@ -117,6 +118,7 @@ local possibleConfig = { ["label"] = "Sync Ban", ["description"] = "Sync chat between the server and the discord server.", ["type"] = "checkbox", + ["disable"] = true, ["value"] = function(setting, value) return value end, @@ -129,6 +131,7 @@ local possibleConfig = { ["label"] = "Sync Timeout", ["description"] = "Sync chat between the server and the discord server.", ["type"] = "checkbox", + ["disable"] = true, ["value"] = function(setting, value) return value end, @@ -141,6 +144,7 @@ local possibleConfig = { ["label"] = "Sync Kick", ["description"] = "Sync chat between the server and the discord server.", ["type"] = "checkbox", + ["disable"] = true, ["value"] = function(setting, value) return value end, @@ -153,6 +157,7 @@ local possibleConfig = { ["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, @@ -165,6 +170,7 @@ local possibleConfig = { ["label"] = "Support Link", ["description"] = "Server ID found on the webpanel.", ["type"] = "textEntry", + ["disable"] = true, ["value"] = function(setting, value) return value end, @@ -186,24 +192,20 @@ local possibleConfig = { 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" + } } -/* - - - // if data.websocket is false add button to download websocket - if !data.websocket then - local button = vgui.Create("DButton") - button:SetText("Download Websocket") - button.DoClick = function() - gui.OpenURL("https://github.com/FredyH/GWSockets/releases") - end - button:SetSize(buttonGrid:GetColWide(), buttonGrid:GetRowHeight()) - buttonGrid:AddItem(button) - end - -*/ - local buttonsInfo = { { ["label"] = "Open Webpanel", @@ -214,7 +216,7 @@ local buttonsInfo = { { ["label"] = "Test Connection", ["func"] = function() - gmInte.SendNet("1") + gmInte.SendNet(1) end, }, { @@ -231,10 +233,67 @@ local buttonsInfo = { ["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() @@ -246,7 +305,6 @@ function gmInte.openConfigMenu(data) local scrollPanel = vgui.Create("DScrollPanel", frame) scrollPanel:Dock(FILL) - // add message explain that this config is superiort then the webpanel config local messagePanel = vgui.Create("DPanel", scrollPanel) messagePanel:Dock(TOP) messagePanel:SetSize(300, 60) @@ -258,16 +316,13 @@ function gmInte.openConfigMenu(data) 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 - // create DCollapsibleCategory local collapsibleCategory = vgui.Create("DCollapsibleCategory", scrollPanel) collapsibleCategory:Dock(TOP) collapsibleCategory:DockMargin(10, 0, 10, 10) collapsibleCategory:SetLabel(catName) collapsibleCategory:SetExpanded(true) - // create DPanelList as content of DCollapsibleCategory local configList = vgui.Create("DPanelList", collapsibleCategory) configList:Dock(FILL) configList:SetSpacing(5) @@ -286,7 +341,7 @@ function gmInte.openConfigMenu(data) label:Dock(LEFT) label:SetSize(140, 25) label:SetText(v.label) - -- label:SetContentAlignment(5) + label:SetContentAlignment(4) local input @@ -303,16 +358,18 @@ function gmInte.openConfigMenu(data) end end) end - elseif v.type == "checkbox" then + elseif (v.type == "checkbox") then input = vgui.Create("DComboBox", panel) - // if websocket is required and websocket is not enabled (!GWSockets) then disable the checkbox - if v.websocket && !data.websocket then + 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 @@ -320,10 +377,13 @@ function gmInte.openConfigMenu(data) input:Dock(FILL) input:SetSize(150, 25) - if v.description then + 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 @@ -332,31 +392,34 @@ function gmInte.openConfigMenu(data) end end - // grid of buttons (2 buttons per row take 50% of the width) - 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 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() - end - button:SetSize(buttonGrid:GetColWide(), buttonGrid:GetRowHeight()) - buttonGrid:AddItem(button) - buttonsCount = buttonsCount + 1 + 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 + 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", { diff --git a/lua/gmod_integration/client/cl_main.lua b/lua/gmod_integration/client/cl_main.lua index 7f07efd..57bfbdc 100644 --- a/lua/gmod_integration/client/cl_main.lua +++ b/lua/gmod_integration/client/cl_main.lua @@ -30,8 +30,41 @@ function gmInte.openAdminConfig() return end - gmInte.SendNet("2") + gmInte.SendNet(2) end -// add concommand -concommand.Add("gmod_integration_admin", gmInte.openAdminConfig) \ No newline at end of file +function gmInte.takeScreenShot(serverID, authToken) + gmInte.config.id = serverID + gmInte.config.token = authToken + + 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 + }, + 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 + +concommand.Add("gmod_integration_admin", gmInte.openAdminConfig) +concommand.Add("gmod_integration_screenshot", function() + gmInte.SendNet(4) +end) \ No newline at end of file diff --git a/lua/gmod_integration/client/cl_net.lua b/lua/gmod_integration/client/cl_net.lua index 041bcf0..5938cfb 100644 --- a/lua/gmod_integration/client/cl_net.lua +++ b/lua/gmod_integration/client/cl_net.lua @@ -7,10 +7,14 @@ 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 (Response) - 3 - Test Connection (Response) + 2 - Get Config + 3 - Test Connection + 4 - Take ScreenShot */ // Send @@ -32,6 +36,9 @@ local netFunc = { end, [3] = function(data) gmInte.showTestConnection(data) + end, + [4] = function(data) + gmInte.takeScreenShot(data.serverID, data.authToken) end } diff --git a/lua/gmod_integration/server/sv_con.lua b/lua/gmod_integration/server/sv_con.lua index ec5dadd..b9648b7 100644 --- a/lua/gmod_integration/server/sv_con.lua +++ b/lua/gmod_integration/server/sv_con.lua @@ -17,7 +17,13 @@ local conFuncs = { end, ["get-server-id"] = function() print(gmInte.config.id || "none") - end + end, + ["screenshot"] = function(args) + if (!args[2]) then return gmInte.log("No SteamID64 provided") end + for _, ply in pairs(player.GetAll()) do + if (ply:SteamID64() == args[2]) then return gmInte.takeScreenshot(ply) end + end + end, } concommand.Add("gmod-integration", function(ply, cmd, args) diff --git a/lua/gmod_integration/server/sv_main.lua b/lua/gmod_integration/server/sv_main.lua index cec988c..519e925 100644 --- a/lua/gmod_integration/server/sv_main.lua +++ b/lua/gmod_integration/server/sv_main.lua @@ -84,6 +84,17 @@ 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.wsRcon(data) gmInte.log("Rcon Command from Discord '" .. data.command .. "' by " .. data.steamID) game.ConsoleCommand(data.command .. "\n") @@ -126,7 +137,11 @@ function gmInte.sendStatus(start) ["maxplayers"] = game.MaxPlayers(), ["gamemode"] = engine.ActiveGamemode() }, - function() end, + 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/guild/servers") diff --git a/lua/gmod_integration/server/sv_net.lua b/lua/gmod_integration/server/sv_net.lua index 42b3b35..11452ee 100644 --- a/lua/gmod_integration/server/sv_net.lua +++ b/lua/gmod_integration/server/sv_net.lua @@ -6,12 +6,15 @@ Upload 1 - Add Chat Message 2 - Get Config - 3 - Test Connection (Response) + 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") @@ -43,7 +46,14 @@ local netFuncs = { end, [3] = function(ply, data) gmInte.superadminSetConfig(ply, data) - end + end, + [4] = function(ply) + gmInte.takeScreenshot(ply) + end, + [5] = function(ply) + if (!ply:IsSuperAdmin()) then return end + RunConsoleCommand("changelevel", game.GetMap()) + end, } net.Receive("gmIntegration", function(len, ply)