dobrograd-13-06-2022/garrysmod/addons/util-fprofiler/lua/fprofiler/ui/servercontrol.lua
Jonny_Bro (Nikita) e4d5311906 first commit
2023-11-16 15:01:19 +05:00

228 lines
6.8 KiB
Lua

local get, update, onUpdate = FProfiler.UI.getModelValue, FProfiler.UI.updateModel, FProfiler.UI.onModelUpdate
--[[-------------------------------------------------------------------------
Update the current selected focus object when data is entered
---------------------------------------------------------------------------]]
onUpdate({"server", "focusStr"}, function(new)
if not new or get({"server", "fromServer"}) then return end
net.Start("FProfile_focusObj")
net.WriteString(new)
net.SendToServer()
end)
net.Receive("FProfile_focusObj", function()
update({"server", "focusObj"}, net.ReadBool() and get({"server", "focusStr"}) or nil)
end)
-- A focus update occurs when someone else changes the focus
net.Receive("FProfile_focusUpdate", function()
update({"server", "fromServer"}, true)
local focusStr = net.ReadString()
update({"server", "focusStr"}, focusStr)
update({"server", "focusObj"}, net.ReadBool() and focusStr or nil)
update({"server", "fromServer"}, false)
end)
--[[-------------------------------------------------------------------------
(Re)start profiling
---------------------------------------------------------------------------]]
local function restartProfiling()
local shouldReset = get({"server", "shouldReset"})
net.Start("FProfile_startProfiling")
net.WriteBool(shouldReset)
net.SendToServer()
end
net.Receive("FProfile_startProfiling", function()
update({"server", "fromServer"}, true)
update({"server", "status"}, "Started")
update({"server", "recordTime"}, net.ReadDouble())
update({"server", "sessionStart"}, net.ReadDouble())
update({"server", "fromServer"}, false)
end)
--[[-------------------------------------------------------------------------
Stop profiling
---------------------------------------------------------------------------]]
local function stopProfiling()
net.Start("FProfile_stopProfiling")
net.SendToServer()
end
-- Read a row from a net message
local function readDataRow(countSize, readSpecific)
local res = {}
local count = net.ReadUInt(countSize)
for i = 1, count do
local row = {}
row.info = {}
row.func = net.ReadString()
row.info.short_src = net.ReadString()
row.info.linedefined = net.ReadUInt(16)
row.info.lastlinedefined = net.ReadUInt(16)
readSpecific(row)
table.insert(res, row)
end
return res
end
-- Read a bottleneck row
local function readBottleneckRow(row)
local nameCount = net.ReadUInt(8)
row.names = {}
for i = 1, nameCount do
table.insert(row.names, {
name = net.ReadString(),
namewhat = net.ReadString()
})
end
row.total_called = net.ReadUInt(32)
row.total_time = net.ReadDouble()
row.average_time = net.ReadDouble()
end
-- Read the top n row
local function readTopNRow(row)
row.info.name = net.ReadString()
row.info.namewhat = net.ReadString()
row.runtime = net.ReadDouble()
end
net.Receive("FProfile_stopProfiling", function()
update({"server", "fromServer"}, true)
update({"server", "status"}, "Stopped")
update({"server", "sessionStart"}, nil)
update({"server", "recordTime"}, net.ReadDouble())
update({"server", "bottlenecks"}, readDataRow(16, readBottleneckRow))
update({"server", "topLagSpikes"}, readDataRow(8, readTopNRow))
update({"server", "fromServer"}, false)
end)
--[[-------------------------------------------------------------------------
Start/stop recording when the recording status is changed
---------------------------------------------------------------------------]]
onUpdate({"server", "status"}, function(new, old)
if new == old or get({"server", "fromServer"}) then return end
(new == "Started" and restartProfiling or stopProfiling)()
end)
--[[-------------------------------------------------------------------------
Update info when a different line is selected
---------------------------------------------------------------------------]]
onUpdate({"server", "currentSelected"}, function(new)
if not new or not new.info or not new.info.linedefined or not new.info.lastlinedefined or not new.info.short_src then return end
-- net.Start("FProfile_getSource")
-- net.WriteString(tostring(new.func))
-- net.SendToServer()
end)
net.Receive("FProfile_getSource", function()
update({"server", "sourceText"}, net.ReadString())
end)
--[[-------------------------------------------------------------------------
When a function is to be printed to console
---------------------------------------------------------------------------]]
onUpdate({"server", "toConsole"}, function(data)
if not data then return end
update({"server", "toConsole"}, nil)
-- net.Start("FProfile_printFunction")
-- net.WriteBool(data.total_called and true or false) -- true for bottleneck function, false for top-n function
-- net.WriteString(tostring(data.func))
-- net.SendToServer()
end)
net.Receive("FProfile_printFunction", function(len)
local data = net.ReadData(len)
local decompressed = util.Decompress(data)
-- Print the text line by line, otherwise big parts of big data will not be printed
local split = string.Explode("\n", decompressed, false)
for _, line in ipairs(split) do
MsgN(line)
end
-- Write the thing to a file
file.CreateDir("fprofiler")
file.Write("fprofiler/profiledata.txt", showStr(data))
MsgC(Color(200, 200, 200), "-----", Color(120, 120, 255), "NOTE", Color(200, 200, 200), "---------------\n")
MsgC(Color(200, 200, 200), "In the server's console you can find a colour coded version of the above output.\nIf the above function does not fit in console, you can find it in data/fprofiler/profiledata.txt\n\n")
end)
--[[-------------------------------------------------------------------------
Check access when the frame opens
Also request a full serverside model update
---------------------------------------------------------------------------]]
onUpdate("frameVisible", function(isOpen)
-- Don't network if the server doesn't have FProfiler installed
if util.NetworkStringToID("FProfile_fullModelUpdate") == 0 then
update("serverAccess", false)
return
end
-- Update access
CAMI.PlayerHasAccess(LocalPlayer(), "FProfiler", function(b, _)
update("serverAccess", b)
end)
if not isOpen then
net.Start("FProfile_unsubscribe")
net.SendToServer()
return
end
net.Start("FProfile_fullModelUpdate")
net.SendToServer()
end)
net.Receive("FProfile_fullModelUpdate", function()
update({"server", "fromServer"}, true)
local focusExists = net.ReadBool()
if focusExists then
local focus = net.ReadString()
update({"server", "focusObj"}, focus)
update({"server", "focusStr"}, focus)
end
local startingTimeExists = net.ReadBool()
if startingTimeExists then
update({"server", "status"}, "Started")
update({"server", "sessionStart"}, net.ReadDouble())
else
update({"server", "status"}, "Stopped")
end
update({"server", "recordTime"}, net.ReadDouble())
update({"server", "bottlenecks"}, readDataRow(16, readBottleneckRow))
update({"server", "topLagSpikes"}, readDataRow(8, readTopNRow))
update({"server", "fromServer"}, false)
end)