ULX

Author Topic: What's the best way of getting a list of ulx chat commands?  (Read 2791 times)

0 Members and 2 Guests are viewing this topic.

Offline iSnipeu

  • Jr. Member
  • **
  • Posts: 83
  • Karma: 12
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: [Select]
gimp:setOpposite( "ulx ungimp", {_, _, true}, "!ungimp" )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: [Select]
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 )

Offline Stickly Man!

  • Ulysses Team Member
  • Hero Member
  • *****
  • Posts: 1270
  • Karma: 164
  • What even IS software anymore?
    • XGUI
Re: What's the best way of getting a list of ulx chat commands?
« Reply #1 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.
Join our Team Ulysses community discord! https://discord.gg/gR4Uye6

Offline iSnipeu

  • Jr. Member
  • **
  • Posts: 83
  • Karma: 12
Re: What's the best way of getting a list of ulx chat commands?
« Reply #2 on: July 07, 2015, 10:39:42 PM »
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.

It wouldn't be registered in the on the client due to the if block having a SERVER check in it.

Offline Stickly Man!

  • Ulysses Team Member
  • Hero Member
  • *****
  • Posts: 1270
  • Karma: 164
  • What even IS software anymore?
    • XGUI
Re: What's the best way of getting a list of ulx chat commands?
« Reply #3 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: [Select]
> print( ULib.cmds.translatedCmds["ulx gag"] == ULib.cmds.translatedCmds["ulx ungag"] )...
true

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: [Select]
> PrintTable( ULib.cmds.translatedCmds["ulx gag"] )...
    <truncated>
opposite = ulx ungag
oppositeArgs:
3 = true
say_cmd:
1 = !gag

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.
« Last Edit: July 08, 2015, 08:45:42 AM by Stickly Man! »
Join our Team Ulysses community discord! https://discord.gg/gR4Uye6

Offline iSnipeu

  • Jr. Member
  • **
  • Posts: 83
  • Karma: 12
Re: What's the best way of getting a list of ulx chat commands?
« Reply #4 on: July 09, 2015, 02:20:00 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: [Select]
> print( ULib.cmds.translatedCmds["ulx gag"] == ULib.cmds.translatedCmds["ulx ungag"] )...
true

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: [Select]
> PrintTable( ULib.cmds.translatedCmds["ulx gag"] )...
    <truncated>
opposite = ulx ungag
oppositeArgs:
3 = true
say_cmd:
1 = !gag

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.

This is what I have at the moment, not sure if it could be done any better
Code: [Select]
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 )

[vid]https://dl.dropboxusercontent.com/u/143570378/ShareX/2015/07/2015-07-09_16-46-20.mp4[/vid]
(how to embed videos?)
« Last Edit: July 09, 2015, 02:24:54 AM by iSnipeu »

Offline Stickly Man!

  • Ulysses Team Member
  • Hero Member
  • *****
  • Posts: 1270
  • Karma: 164
  • What even IS software anymore?
    • XGUI
Re: What's the best way of getting a list of ulx chat commands?
« Reply #5 on: July 09, 2015, 03:01:29 PM »
Apparently, we don't have any way to embed videos. :( (There is a [flash] tag for YouTube though)

Only suggestion I have after a quick glance at the code, maybe you could store suggestionLimit:GetInt() in a local variable so it doesn't have to parse the convar too frequently? (I've never measured performance of that.. It probably won't make a huge difference either way)

Otherwise, I think it looks great!
Join our Team Ulysses community discord! https://discord.gg/gR4Uye6