lsft/sv_lsft.txt

445 lines
16 KiB
Text
Raw Normal View History

2021-12-14 20:11:04 -05:00
--@name Logan's Starfall Toolkit
--@author logan2611
--@server
--@include lsft/cl_lsft.txt
--@includedir lsft/modules/server
--@includedir lsft/modules/shared
--@clientmain lsft/cl_lsft.txt
-- SPAWN THIS ONE
--[[
_ ____ _____ _____
| | / ___|| ___|_ _|
| | _____ \___ \| |_ | |
| |___ |_____| ___) | _| | |
|_____| |____/|_| |_|
--]]
--[[
TODO: Update checker
TODO: On module load, grab default config values. Write changed values
prop.createSent(chip():getPos()+Vector(0,0,90),Angle(0,0,0),"Seat_Airboat",true)
--]]
-- Main Module (Mostly loading modules and stuff)
core = {}
do
local function stats()
net.start("LSFT-StatsRequest")
net.send()
local peakClientCPUTime = 0
local peakClientCPUPercent = 0
local peakClientRAM = 0
local peakClientRAMPercent = 0
local minClientNet = 2^31
local plys = 0
local function displayStats()
2022-03-26 04:34:32 -04:00
core:logConsole(log.TEXT, "---------------------------")
core:logConsole(log.TEXT, "Server Stats:")
core:logConsole(log.INFO, "Max CPU: ", core.colors.text, math.round(core.maxCPU*1000000).."us ("..math.round(core.maxCPU*100/quotaMax()).."%)")
core:logConsole(log.INFO, "Max RAM: ", core.colors.text, math.round(core.maxRAM).."kB ("..math.round(core.maxRAM*100/ramMax()).."%)")
core:logConsole(log.INFO, "Min Net: ", core.colors.text, core.minNet.." bytes")
core:logConsole(log.TEXT, "")
core:logConsole(log.TEXT, "Client Stats:")
core:logConsole(log.INFO, "Max CPU: ", core.colors.text, math.round(peakClientCPUTime*1000000).."us")
core:logConsole(log.INFO, "Max CPU %: ", core.colors.text, math.round(peakClientCPUPercent*100, 2).."%")
core:logConsole(log.INFO, "Max RAM: ", core.colors.text, math.round(peakClientRAM).."kB")
core:logConsole(log.INFO, "Max RAM %: ", core.colors.text, math.round(peakClientRAMPercent*100, 2).."%")
core:logConsole(log.INFO, "Min Net: ", core.colors.text, minClientNet.." bytes")
core:logConsole(log.INFO, "Errored Clients: ", core.colors.text, #chip():getErroredPlayers())
core:logConsole(log.TEXT, "---------------------------")
core:log(log.INFO, "Finished, check your developer console.")
end
timer.create("displaystats", 5, 1, displayStats)
net.receive("LSFT-StatsResponse", function()
plys = plys + 1
local clientCPUTime = net.readFloat()
local clientCPUPercent = clientCPUTime/net.readFloat()
local clientRAM = net.readFloat()
local clientRAMPercent = clientRAM/net.readFloat()
local clientNet = net.readFloat()
-- Comparison
if clientCPUTime > peakClientCPUTime then peakClientCPUTime = clientCPUTime end
if clientCPUPercent > peakClientCPUPercent then peakClientCPUPercent = clientCPUPercent end
if clientRAM > peakClientRAM then peakClientRAM = clientRAM end
if clientRAMPercent > peakClientRAMPercent then peakClientRAMPercent = clientRAMPercent end
if clientNet < minClientNet then minClientNet = clientNet end
-- If we have gotten a response from everyone, fuck the timer
-- There is a function that tells us when players are ready to receive stuff, but idk where it is and I'm too lazy to make one
if plys == #find.allPlayers() then timer.remove("displaystats") displayStats() end
end)
core:log(log.INFO, "Collecting data, please wait...")
end
local function hud()
if core.hud then
enableHud(owner(),false)
core.hud = false
else
enableHud(owner(),true)
core.hud = true
end
end
local function help(args)
local module = args[1]
local command = args[2]
if module == nil and command == nil then
core:log(log.TEXT, "---------------------------")
core:log(log.INFO, "To list the commands in a module, type "..core:get_config("core", "command_prefix").."help <module>")
core:log(log.INFO, "List of available modules:")
local modules = {}
for i, v in pairs(core.modules) do
table.insert(modules, core.colors.logo)
table.insert(modules, "[L-SFT] ")
table.insert(modules, core.colors.info)
table.insert(modules, "\""..i.."\" | ")
table.insert(modules, core.colors.text)
table.insert(modules, (v.desc or "No description provided.").."\n")
end
modules[#modules] = modules[#modules]:sub(1, -2)
print(unpack(modules))
core:log(log.TEXT, "---------------------------")
elseif module ~= nil and command == nil then
if not core.modules[module] then core:log(log.ERROR, "Module does not exist!") return end
core:log(log.TEXT, "---------------------------")
core:log(log.INFO, "List of available commands in module \""..module.."\":")
local commands = {}
for i, v in pairs(core.modules[module].commands) do
table.insert(commands, core.colors.logo)
table.insert(commands, "[L-SFT] ")
table.insert(commands, core.colors.info)
table.insert(commands, "\""..i.."\" | Usage: ")
table.insert(commands, core.colors.text)
table.insert(commands, (v.usage or "No usage provided.").."\n")
end
commands[#commands] = commands[#commands]:sub(1, -2)
print(unpack(commands))
core:log(log.TEXT, "---------------------------")
elseif module ~= nil and command ~= nil then
if not core.modules[module].commands[command] then core:log(log.ERROR, "Command does not exist in module \""..module.."\"!") return end
core:log(log.TEXT, "---------------------------")
core:log(log.INFO, "Usage: ", core.colors.text, (core.modules[module].commands[command].usage or "Command: "..command.." (No usage provided)"))
core:log(log.INFO, "Description: ", core.colors.text, (core.modules[module].commands[command].desc or "No description provided."))
core:log(log.TEXT, "---------------------------")
else
core:log(log.ERROR, "Universe is broken.")
end
end
core.modules = {
core = {
version = 0.1,
desc = "Built in module.",
commands = {
stats = {
func = stats,
usage = "stats",
desc = "Gets performance information about this Starfall chip.",
},
hud = {
func = hud,
usage = "hud",
desc = "Toggles the built in Starfall HUD.",
},
help = {
desc = "List modules, list commands in a module or gets information about a specific command.",
usage = "help [module] [command]",
func = help,
},
},
2021-12-14 20:11:04 -05:00
},
}
end
2021-12-14 20:11:04 -05:00
core.config = {}
core.defaultconfig = {
core = {
command_prefix = "!n",
colors = {
logo = Color(255,200,50),
text = Color(255,255,255),
info = Color(150,200,255),
warn = Color(255,120,50),
error = Color(255,50,50),
},
controls = {
forward = KEY.W,
backward = KEY.S,
left = KEY.A,
right = KEY.D,
up = KEY.SPACE,
down = KEY.CTRL,
run = KEY.SHIFT,
},
2021-12-14 20:11:04 -05:00
},
}
core.colors = {}
core.maxCPU = 0
core.minNet = net.getBytesLeft()
core.maxRAM = 0
2021-12-14 20:11:04 -05:00
log = {
ERROR=0,
WARNING=1,
INFO=2,
TEXT=3
}
function core:init(config)
-- If the streamed config exists and has stuff in it, use it instead of the empty one
if config != nil and #config > 0 then
core.config = config
end
core:load_modules()
local hud = prop.createComponent(chip():getPos(), Angle(0,0,0), "starfall_hud", "models/bull/dynamicbutton.mdl", true)
hud:linkComponent(chip())
hud:setSolid(false)
hud:setColor(Color(255,255,255,0))
enableHud(owner(), true)
core.hud = true
2022-03-26 01:45:36 -04:00
prop.setPropClean(true)
core.colors.logo = core:get_config("core","colors","logo")
core.colors.text = core:get_config("core","colors","text")
core.colors.info = core:get_config("core","colors","info")
core.colors.warn = core:get_config("core","colors","warn")
core.colors.error = core:get_config("core","colors","error")
core.command_prefix = core:get_config("core","command_prefix")
2021-12-14 20:11:04 -05:00
core:log(log.INFO, "Loaded v"..core.modules.core.version.." successfully")
net.start("LSFT-Loaded")
net.send()
2021-12-14 20:11:04 -05:00
return true
end
function core:get_config(...)
local args = {...}
local cur = core.config
for arg in pairs(args) do
for i,v in pairs(cur) do
if i == args[arg] then
if type(v) == "table" then
--cur = cur[i]
cur = v
continue
else
return v
end
end
end
end
local cur = core.defaultconfig
for arg in pairs(args) do
for i,v in pairs(cur) do
if i == args[arg] then
if type(v) == "table" then
--cur = cur[i]
cur = v
continue
else
return v
end
end
end
end
error("Config value requested, but no current or default entry exists!")
end
function core:load_modules()
dodir("lsft/modules/server")
dodir("lsft/modules/shared")
hook.add("PlayerSay", "CommandCheck", function(ply, str)
if ply == owner() and string.find(str, "^"..core.command_prefix) then
local stringin = string.explode(" ", str)
local command = string.sub(stringin[1], #core.command_prefix+1)
local args = {}
for i, v in pairs(stringin) do
if i == 1 then continue end
table.insert(args, v)
end
2021-12-14 20:11:04 -05:00
for i, v in pairs(core.modules) do
for commandin, commandthing in pairs(v["commands"]) do
2021-12-14 20:11:04 -05:00
if command == commandin then
try(
function() commandthing.func({unpack(args)}) end,
function(err) core:log(log.ERROR, "Error executing command \""..str.."\"!") core:log(log.ERROR, "Reason: "..err["message"]) end
)
2021-12-14 20:11:04 -05:00
return ""
end
end
end
--print(core.color_logo, "[L-SFT] ", core.color_error, "Error: \""..command.."\" is not a valid command!")
core:log(log.ERROR, "\""..command.."\" is not a valid command!")
return ""
end
end)
end
function core:log(...)
local args = {...}
local loglevel = args[1]
local message = { unpack(args, 2, #args) }
local color = Color(0,0,0)
if loglevel == log.ERROR then color = core.colors.error
elseif loglevel == log.WARNING then color = core.colors.warn
elseif loglevel == log.INFO then color = core.colors.info
elseif loglevel == log.TEXT then color = core.colors.text
2021-12-14 20:11:04 -05:00
end
print(core.colors.logo, "[L-SFT] ", color, unpack(message))
2021-12-14 20:11:04 -05:00
end
2022-03-26 01:46:18 -04:00
function core:logConsole(...)
local args = {...}
local loglevel = args[1]
local message = { unpack(args, 2, #args) }
local color = Color(0,0,0)
if loglevel == log.ERROR then color = core.colors.error
elseif loglevel == log.WARNING then color = core.colors.warn
elseif loglevel == log.INFO then color = core.colors.info
elseif loglevel == log.TEXT then color = core.colors.text
end
printConsole(core.colors.logo, "[L-SFT] ", color, unpack(message))
end
-- Get's a player's entity by searching for it via an inputted string
function core:get_entity(ply)
if type(ply) == "Player" then
return ply
elseif ply == "^" then
return owner()
end
local targets = find.playersByName(ply)
if #targets == 0 or targets == nil then
core:log(log.ERROR, "No targets found!")
return nil
elseif #targets > 1 then
local list = ""
for i, v in pairs(target) do
list = list..v..", "
end
list:sub(1, -2)
core:log(log.ERROR, "Muliple targets found! ("..list..")")
return nil
end
return targets[1]
end
2021-12-14 20:11:04 -05:00
net.receive("LSFT-Config-Read", function(len, ply)
if ply == owner() then
-- Colors settings aren't loaded yet, so use dumb printing method with default colors (Don't ever do this >:c)
--print(core.defaultconfig.core.color_logo, "[L-SFT] ", core.defaultconfig.core.color_info, "Downloading configuration: 0%")
timer.create("ConfigProgress", 0.25, 0, function()
print(core.defaultconfig.core.colors.logo, "[L-SFT] ", core.defaultconfig.core.colors.info, "Downloading configuration: ", math.round(net.getStreamProgress() * 100, 2), "%")
2021-12-14 20:11:04 -05:00
end)
net.readStream(function(data)
timer.remove("ConfigProgress")
core:init(json.decode(data))
end)
else
print(core.defaultconfig.core.colors.logo, "[L-SFT] ", core.defaultconfig.core.colors.error, ply:getName().." is trying to give us a config")
2021-12-14 20:11:04 -05:00
end
end)
net.receive("LSFT-Get-Config", function()
net.start(net.readString())
local output = {}
while true do
local temp = net.readTable()
if #temp == 0 then break end
net.writeTable({core:get_config(unpack(temp))}) -- what the fuck
end
net.send()
end)
timer.create("CPUCheck", 0.5, 0, function()
if quotaAverage() > core.maxCPU then
core.maxCPU = quotaAverage()
end
2021-12-14 20:11:04 -05:00
if quotaAverage() > quotaMax() * 0.5 then
core:log(log.WARNING, "CPU usage is high! ("..math.round(quotaAverage()*100/quotaMax()).."% remaining)")
elseif quotaAverage() > quotaMax() * 0.9 then
core:log(log.ERROR, "CPU usage is critically high! ("..math.round(quotaAverage()*100/quotaMax()).."% remaining)")
timer.pause("CPUCheck")
timer.pause("NetCheck")
timer.pause("RAMCheck")
timer.simple(10, function() timer.unpause("CPUCheck") timer.unpause("NetCheck") timer.unpause("RAMCheck") end)
end
end)
timer.create("NetCheck", 0.5, 0, function()
if net.getBytesLeft() < core.minNet then
core.minNet = net.getBytesLeft()
end
if net.getBytesLeft() < 3000 then
core:log(log.WARNING, "Network bandwidth is low! ("..net.getBytesLeft().." bytes left)")
elseif net.getBytesLeft() < 1000 then
core:log(log.ERROR, "Network bandwidth is critically low! ("..net.getBytesLeft().." bytes left)")
end
end)
timer.create("RAMCheck", 0.5, 0, function()
if ramUsed() > core.maxRAM then
core.maxRAM = ramUsed()
end
if ramUsed() > ramMax() * 0.5 then
core:log(log.WARNING, "RAM usage is high! ("..math.round(ramUsed()*100/ramMax()).."% used)")
elseif ramUsed() > ramMax() * 0.9 then
core:log(log.ERROR, "RAM usage is critically high! ("..math.round(ramUsed()*100/ramMax()).."% used)")
end
end)