lsft/sv_lsft.txt
Logan Gartner e437bbdc57
Massive improvements
New module system
Added help menu
Added stats command
Added built in HUD
Changed colors to make more sense
Added loaded net message
Improved chat check for commands
Shortened color names
2021-12-16 00:07:35 -07:00

340 lines
12 KiB
Text

--@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()
-- For debugging purposes mostly
core:log(log.TEXT, "---------------------------")
core:log(log.TEXT, "Server Stats:")
core:log(log.INFO, "Max CPU: ", core.colors.text, math.round(core.maxCPU*1000000).."us ("..math.round(core.maxCPU*100/quotaMax()).."%)")
core:log(log.INFO, "Max RAM: ", core.colors.text, math.round(core.maxRAM).."kB ("..math.round(core.maxRAM*100/ramMax()).."%)")
core:log(log.INFO, "Min Net: ", core.colors.text, core.minNet.." bytes")
core:log(log.TEXT, "---------------------------")
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.."\" | "..(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: "..(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.modules[module].commands[command].usage or "Command: "..command.." (No usage provided)"))
core:log(log.INFO, "Description: "..(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,
},
},
},
}
end
core.config = {}
core.defaultconfig = {
core = {
command_prefix = "!n",
colors = {
logo = Color(255,200,50),
text = Color(255,255,255),
info = Color(50,150,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,
},
},
}
core.colors = {}
core.maxCPU = 0
core.minNet = net.getBytesLeft()
core.maxRAM = 0
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
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")
core:log(log.INFO, "Loaded v"..core.modules.core.version.." successfully")
net.start("LSFT-Loaded")
net.send()
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
for i, v in pairs(core.modules) do
for commandin, commandthing in pairs(v["commands"]) do
if command == commandin then
commandthing.func({unpack(args)})
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
end
print(core.colors.logo, "[L-SFT] ", color, unpack(message))
end
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), "%")
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")
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", 1, 0, function()
if quotaAverage() > core.maxCPU then
core.maxCPU = quotaAverage()
end
if quotaAverage() > quotaMax() * 0.5 then
core:log(log.WARNING, "CPU quota is low! ("..math.round(100-(quotaAverage()*100/quotaMax())).."% remaining)")
elseif quotaAverage() > quotaMax() * 0.9 then
core:log(log.ERROR, "CPU quota is critically low! ("..math.round(100-(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", 1, 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", 1, 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)