General > Developers Corner
What's the best way of getting a list of ulx chat commands?
iSnipeu:
I've made a port of the evolve chat autocomplete plugin for ulx but I've noticed that it doesn't include the "undo" chat commands that some ulx commands have. e.g.
--- Code: ---gimp:setOpposite( "ulx ungimp", {_, _, true}, "!ungimp" )
--- End code ---
Picture of what it looks like:
(ignore the hud overlap I've fixed that by changing what hook it draws in)
I'm currently using the "ulx.cmdsByCategory" table for access checking and info to display below the chatbox, here's the code for it.
--- Code: ---local inChat = false
hook.Add( "StartChat", "UlxChatComplete", function() inChat = true end )
hook.Add( "FinishChat", "UlxChatComplete", function() inChat = false end )
local shouldDraw = CreateClientConVar( "ulx_chatcomplete", "1", true, false )
local ulxSuggestions = {}
hook.Add( "PostDrawHUD", "UlxChatComplete", function()
if shouldDraw:GetBool() and inChat then
local x, y = chat.GetChatBoxPos()
x = x + ScrW() * 0.037
y = y + ScrH() / 4 + 5
local font = "ChatFont"
surface.SetFont( font )
for _, v in ipairs( ulxSuggestions ) do
local x1, y1 = surface.GetTextSize( v.ChatCommand )
local x2, _ = surface.GetTextSize( v.Usage )
draw.SimpleTextOutlined( v.ChatCommand, font, x, y, Color(255, 255, 100, 255), _, _, 0.5, Color(0, 0, 0, 255) )
draw.SimpleTextOutlined( " "..v.Usage.." ", font, x + x1, y, Color(255, 255, 255, 255), _, _, 0.5, Color(0, 0, 0, 255) )
draw.SimpleTextOutlined( " - "..v.Help.." ", font, x + x1 + x2, y, Color(255, 255, 255, 255), _, _, 0.5, Color(0, 0, 0, 255) )
y = y + y1
end
end
end )
local suggestionLimit = CreateClientConVar( "ulx_chatcomplete_limit", "4", true, false )
hook.Add( "ChatTextChanged", "UlxChatComplete", function( str )
ulxSuggestions = {}
local com = string.sub( str, 1, (string.find(str, " ") or (#str + 1)) - 1 )
if #com >= 1 and ( string.sub(com, 0, 1) != "!" or #com >= 2 ) then
local ply = LocalPlayer()
for category, cmds in pairs( ulx.cmdsByCategory ) do
for _, cmd in ipairs( cmds ) do
local tag = cmd.cmd
if cmd.manual then
tag = cmd.access_tag
end
local str = cmd:superClass().getUsage( cmd, ply )
if ULib.ucl.query( ply, tag ) and istable( cmd.say_cmd ) then
for k, ccmd in pairs( cmd.say_cmd ) do
if string.sub( ccmd, 0, #com ) == string.lower( com ) and #ulxSuggestions < suggestionLimit:GetInt() then
local suggestion = {}
suggestion.ChatCommand = ccmd
suggestion.Usage = str:Trim() or ""
suggestion.Help = cmd.helpStr or ""
table.insert( ulxSuggestions, suggestion )
end
end
end
end
end
table.SortByMember( ulxSuggestions, "ChatCommand", function( a, b )
return a < b
end )
end
end )
--- End code ---
Stickly Man!:
Looks neat! ;D
Unless I'm mistaken, all chat commands get registered through ULib's ULib.addSayCommand function.
Looking at the code, this information should be accessible in the ULib.sayCmds table. I'm not if this table is available clientside, though (This line seems to suggest that it is). If it's not, you may be able to look into how ULX does the autocompletes for console. Megiddo would know much more about how that's put together.
iSnipeu:
--- Quote from: Stickly Man! on July 06, 2015, 10:15:55 AM ---Looks neat! ;D
Unless I'm mistaken, all chat commands get registered through ULib's ULib.addSayCommand function.
Looking at the code, this information should be accessible in the ULib.sayCmds table. I'm not if this table is available clientside, though (This line seems to suggest that it is). If it's not, you may be able to look into how ULX does the autocompletes for console. Megiddo would know much more about how that's put together.
--- End quote ---
It wouldn't be registered in the on the client due to the if block having a SERVER check in it.
Stickly Man!:
Ah, you're right, I completely missed that "if SERVER" check.
Digging into it further, it seems like your best option may be to simply generate a list of chat commands using ULib.sayCmds table on the server, then pass it along to the client soon after they join.
Essentially, the ulx.cmdsByCategory table references ULib.cmds.translatedCmds. You could iterate through that to save a for loop, but even then, the opposite commands listed there are literally a direct reference to the primary command:
--- Code: ---> print( ULib.cmds.translatedCmds["ulx gag"] == ULib.cmds.translatedCmds["ulx ungag"] )...
true
--- End code ---
On top of that, the opposite data for a command doesn't store its chat command: (This may be something we want to look into)
--- Code: ---> PrintTable( ULib.cmds.translatedCmds["ulx gag"] )...
<truncated>
opposite = ulx ungag
oppositeArgs:
3 = true
say_cmd:
1 = !gag
--- End code ---
And lastly, some chat commands are registered manually via ULib.addSayCommand, and as far as I'm aware, there are no references to it on the client. (XGUI is one example- !menu and !xgui are valid commands that I was too lazy or didn't need to create a full ULX command for).
.. So yeah, I'd definitely recommend sending your own table over from the server using ULib.sayCmds. The table also stores the access required for each chat command (nil for everyone), so you can easily check if the player can run it or not.
iSnipeu:
--- Quote from: Stickly Man! on July 08, 2015, 08:42:03 AM ---Ah, you're right, I completely missed that "if SERVER" check.
Digging into it further, it seems like your best option may be to simply generate a list of chat commands using ULib.sayCmds table on the server, then pass it along to the client soon after they join.
Essentially, the ulx.cmdsByCategory table references ULib.cmds.translatedCmds. You could iterate through that to save a for loop, but even then, the opposite commands listed there are literally a direct reference to the primary command:
--- Code: ---> print( ULib.cmds.translatedCmds["ulx gag"] == ULib.cmds.translatedCmds["ulx ungag"] )...
true
--- End code ---
On top of that, the opposite data for a command doesn't store its chat command: (This may be something we want to look into)
--- Code: ---> PrintTable( ULib.cmds.translatedCmds["ulx gag"] )...
<truncated>
opposite = ulx ungag
oppositeArgs:
3 = true
say_cmd:
1 = !gag
--- End code ---
And lastly, some chat commands are registered manually via ULib.addSayCommand, and as far as I'm aware, there are no references to it on the client. (XGUI is one example- !menu and !xgui are valid commands that I was too lazy or didn't need to create a full ULX command for).
.. So yeah, I'd definitely recommend sending your own table over from the server using ULib.sayCmds. The table also stores the access required for each chat command (nil for everyone), so you can easily check if the player can run it or not.
--- End quote ---
This is what I have at the moment, not sure if it could be done any better
--- Code: ---inChat = inChat or false
hook.Add( "StartChat", "UlxChatComplete", function() inChat = true end )
hook.Add( "FinishChat", "UlxChatComplete", function() inChat = false end )
local shouldDraw = CreateClientConVar( "ulx_chatcomplete", "1", true, false )
ulxSuggestions = ulxSuggestions or {}
hook.Add( "PostDrawHUD", "UlxChatComplete", function()
if shouldDraw:GetBool() and inChat then
local x, y = chat.GetChatBoxPos()
x = x + ScrW() * 0.037
y = y + ScrH() / 4 + 5
local font = "ChatFont"
surface.SetFont( font )
for k, v in ipairs( ulxSuggestions ) do
local x1, y1 = surface.GetTextSize( v.ChatCommand )
draw.SimpleTextOutlined( v.ChatCommand, font, x, y, Color(255, 255, 100, 255), _, _, 0.5, Color(0, 0, 0, 255) )
draw.SimpleTextOutlined( " "..v.AutoComplete.." ", font, x + x1, y, Color(255, 255, 255, 255), _, _, 0.5, Color(0, 0, 0, 255) )
y = y + y1
end
end
end )
if SERVER then
util.AddNetworkString( "ULibChatCompleteList" )
hook.Add( "PlayerInitialSpawn", "SendULibChatComplete", function( ply )
local ULibsayCmds = table.Copy( ULib.sayCmds )
for k, v in pairs( ULibsayCmds ) do
ULibsayCmds[ k ].fn = nil
end
net.Start( "ULibChatCompleteList" )
net.WriteTable( ULibsayCmds )
net.Send( ply )
end )
else
ULibsayCmds = ULibsayCmds or {}
net.Receive( "ULibChatCompleteList", function()
ULibsayCmds = net.ReadTable()
end )
end
hook.Add( "OnChatTab", "UlxChatComplete", function( str )
if ulxSuggestions and #ulxSuggestions >= 1 then
local suggestion = ulxSuggestions[1]
return suggestion.ChatCommand.." "..suggestion.AutoComplete
end
end )
local suggestionLimit = CreateClientConVar( "ulx_chatcomplete_limit", "4", true, false )
hook.Add( "ChatTextChanged", "UlxChatComplete", function( str )
ulxSuggestions = {}
local com = string.sub( str, 1, (string.find(str, " ") or (#str + 1)) - 1 )
if #com >= 1 and ( string.sub(com, 0, 1) != "!" or #com >= 2 ) then
local ply = LocalPlayer()
for say_cmd, data in pairs( ULibsayCmds ) do
if #ulxSuggestions >= suggestionLimit:GetInt() then
break
end
if !ULib.ucl.query( ply, data.access ) then
continue
end
say_cmd = string.lower( say_cmd ):Trim()
if string.sub( say_cmd, 0, #com ) == string.lower( com ) then
if say_cmd == com then
local cmd = string.sub( data.__cmd, 1, (string.find(data.__cmd, " ") or (#data.__cmd + 1)) - 1 )
local cmd_args = string.sub( data.__cmd, #cmd+2, #data.__cmd )
local chat_args = string.sub( str, #cmd+3, #str )
local complete = concommand.AutoComplete( cmd, cmd_args.." "..chat_args )
if complete and #complete > 0 then
for k, v in pairs( complete ) do
local suggestion = {}
suggestion.ChatCommand = say_cmd
suggestion.AutoComplete = string.sub( v, #data.__cmd+2, #v ):Trim()
table.insert( ulxSuggestions, suggestion )
end
continue
end
end
local suggestion = {}
suggestion.ChatCommand = say_cmd
suggestion.AutoComplete = ""
table.insert( ulxSuggestions, suggestion )
end
end
table.SortByMember( ulxSuggestions, "ChatCommand", function( a, b )
return a < b
end )
end
end )
--- End code ---
[vid]https://dl.dropboxusercontent.com/u/143570378/ShareX/2015/07/2015-07-09_16-46-20.mp4[/vid]
(how to embed videos?)
Navigation
[0] Message Index
[#] Next page
Go to full version