Raised This Month: $12 Target: $400
 3% 

Snippet: Setting RGB/RGBA values via a command


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
404UserNotFound
BANNED
Join Date: Dec 2011
Old 02-24-2018 , 17:30   Snippet: Setting RGB/RGBA values via a command
Reply With Quote #1

Just a little something I've been tinkering with and finally got working the way I want it to. It'll be used in an upcoming update to my old Lo-Fi Longwave Beacon Deluxe plugin but I realize this could be very useful for people wanting an easy way to allow players to choose their own RGB/RGBA values for things like FuncommandsX's colorizing (or in my case, my fully separate player/weapon/cosmetic/building colorizing commands).

I've left some comment notes in there regarding some stuff. Got suggestions for improvement of this code? Send 'em my way!

Regex pattern was obtained from https://www.regular-expressions.info/numericranges.html

Update: Added new version 2 of the commands. Main difference is version 1 uses GetCmdArgString and regex checks the entire string using a huge regex pattern. Version 2 uses individual GetCmdArg's and a significantly smaller regex pattern to check each arg individually.

Version 1 - Tested, Working 100%


Version 2 - Untested

Last edited by 404UserNotFound; 02-25-2018 at 02:07.
404UserNotFound is offline
headline
SourceMod Moderator
Join Date: Mar 2015
Old 02-25-2018 , 03:21   Re: Snippet: Setting RGB/RGBA values via a command
Reply With Quote #2

Why are you so obsessed with regex?

PHP Code:
public Action Command_EnterRGBA(int clientint args)
{
    if (
args != 4)
    {
        
ReplyToCommand(client"[SM] Usage: sm_rgba <0-255> <0-255> <0-255> <0-255>");
        return 
Plugin_Handled;
    }
    if (
client == || !IsClientInGame(client))
    {
        
ReplyToCommand(client"[SM] You must be in-game to use this command!");
        return 
Plugin_Handled;
    }

    
char str1[4], str2[4], str3[4], str4[4];
    
GetCmdArg(1str1sizeof(str1));
    
GetCmdArg(2str2sizeof(str2));
    
GetCmdArg(3str3sizeof(str3));
    
GetCmdArg(4str4sizeof(str4));


    
int r StringToInt(str1);
    if (!(
<= <= 255))
    {
        
ReplyToCommand(client"[SM] Red value is outside the valid range of 0-255.");
        return 
Plugin_Handled;
    }
    
    
int g StringToInt(str2);
    if (!(
<= <= 255))
    {
        
ReplyToCommand(client"[SM] Green value is outside the valid range of 0-255.");
        return 
Plugin_Handled;
    }

    
int b StringToInt(str3);
    if (!(
<= <= 255))
    {
        
ReplyToCommand(client"[SM] Blue value is outside the valid range of 0-255.");
        return 
Plugin_Handled;
    }
    
    
int a StringToInt(str4);
    if (!(
<= <= 255))
    {
        
ReplyToCommand(client"[SM] Alpha value is outside the valid range of 0-255.");
        return 
Plugin_Handled;
    }
    
    
    
// use RGBA how you want
    
return Plugin_Handled;


Last edited by headline; 02-25-2018 at 03:22.
headline is offline
ddhoward
Veteran Member
Join Date: May 2012
Location: California
Old 02-25-2018 , 04:13   Re: Snippet: Setting RGB/RGBA values via a command
Reply With Quote #3

Quote:
Originally Posted by Headline View Post
Why are you so obsessed with regex?

Spoiler
Even this is a little excessive; it's not necessary to hold the user's hand for the range validation, just as it's not necessary to use regex to check for non-numeric characters. Even if they omit an argument, I'd just go with it.

PHP Code:
public Action Command_EnterRGBA(int clientint args) {

    if (
client == || !IsClientInGame(client)) {
        
ReplyToCommand(client"[SM] You must be in-game to use this command!");
        return 
Plugin_Handled;
    }

    
char chRGBA[4][4];
    
int iRGBA[4];
    for (
int isizeof(chRGBA) && argsi++) {
        
GetCmdArg(i+1chRGBA[i], sizeof(chRGBA[i]));
        
iRGBA[i] = StringToInt(chRGBA[i]);
        if (!(
<= iRGBA[i] <= 255)) {
            
iRGBA[i] = 0;
            
ReplyToCommand(client"RGBA values must be between 0 and 255.");
        }
    }
        
    
// use RGBA how you want
    
return Plugin_Handled;

__________________

Last edited by ddhoward; 02-25-2018 at 04:20.
ddhoward is offline
headline
SourceMod Moderator
Join Date: Mar 2015
Old 02-25-2018 , 04:56   Re: Snippet: Setting RGB/RGBA values via a command
Reply With Quote #4

Quote:
Originally Posted by ddhoward View Post
Even this is a little excessive; it's not necessary to hold the user's hand for the range validation, just as it's not necessary to use regex to check for non-numeric characters. Even if they omit an argument, I'd just go with it.

PHP Code:
public Action Command_EnterRGBA(int clientint args) {

    if (
client == || !IsClientInGame(client)) {
        
ReplyToCommand(client"[SM] You must be in-game to use this command!");
        return 
Plugin_Handled;
    }

    
char chRGBA[4][4];
    
int iRGBA[4];
    for (
int isizeof(chRGBA) && argsi++) {
        
GetCmdArg(i+1chRGBA[i], sizeof(chRGBA[i]));
        
iRGBA[i] = StringToInt(chRGBA[i]);
        if (!(
<= iRGBA[i] <= 255)) {
            
iRGBA[i] = 0;
            
ReplyToCommand(client"RGBA values must be between 0 and 255.");
        }
    }
        
    
// use RGBA how you want
    
return Plugin_Handled;

Every code post turns into a pissing contest. It just depends on if you want to coddle the user, and how simple you’d want the code to be. While it could be done with iteration as you’ve shown, it’s a bit much for someone who doesn’t yet grasp the usage of regex. The approach I posted is nearly equivalent to yours, but I tend to avoid assuming user inputs if they’re invalid. Garbage data in -> garbage data out.
headline is offline
404UserNotFound
BANNED
Join Date: Dec 2011
Old 02-25-2018 , 05:20   Re: Snippet: Setting RGB/RGBA values via a command
Reply With Quote #5

Quote:
Originally Posted by Headline View Post
Why are you so obsessed with regex?
I prefer to be a thorough programmer, and to think 10 steps ahead and get in the mindset of the end user who will use my plugin. And I think that's the reason we have if/else if/else statements in the first place, for checking values and ensuring bugs don't arise due to whatever circumstances should cause them, right?

And honestly, who does it hurt if I use Regex And I'm interested in regex, not obsessed with it. I'm in a computer programming course to learn programming, so maybe I should also learn other things related, y'know?.

Quote:
Originally Posted by ddhoward View Post
Even this is a little excessive; it's not necessary to hold the user's hand for the range validation, just as it's not necessary to use regex to check for non-numeric characters. Even if they omit an argument, I'd just go with it.
Holy crap, that looks good. And understandably so, given the huge difference in our skill levels (yours being much higher than mine). But I disagree with it being excessive. It's simple, it does its job. The only real check is the strlen check, and the regex was done because I figured it'd be simpler and it gave me a finer level of control and also prevented me from releasing something like this:

PHP Code:
if (iRed 0iRed 0;
else if (
iRed 255iRed 255;
else if (
iGreen 0iGreen 0;
else if (
iGreen 255iGreen 255;
else if (
iBlue 0iBlue 0;
else if (
iBlue 255iBlue 255;
else if (
iAlpha 0iAlpha 0;
else if (
iAlpha 255iAlpha 255
My next train of thought on the above code would have been "gee, I wonder if I could compress this into "if (iRed < 0 || iGreen < 0 || iBlue < 0 || iAlpha < 0)" and then set up some quick and dirty thing to change the value of the specific integer the check was being done on." You see how quickly this becomes convoluted.

Last edited by 404UserNotFound; 02-25-2018 at 06:19.
404UserNotFound is offline
ddhoward
Veteran Member
Join Date: May 2012
Location: California
Old 02-25-2018 , 06:22   Re: Snippet: Setting RGB/RGBA values via a command
Reply With Quote #6

Quote:
Originally Posted by Headline View Post
Every code post turns into a pissing contest
It is unfortunate that you interpreted this conversation in this way. I was merely joining you in demonstrating to our OP colleague that there are simpler ways to perform the stated task. Your code is more readable, mine is compacter and more easily editable (for example, if a "target" argument were to be prepended to the list of arguments.)


Quote:
Originally Posted by 404UNF View Post
I prefer to be a thorough programmer, and to think 10 steps ahead and get in the mindset of the end user who will use my plugin. And I think that's the reason we have if/else if/else statements in the first place, for checking values and ensuring bugs don't arise due to whatever circumstances should cause them, right?
This is absolutely correct. If you look at some of my earlier work, especially with Friendly Mode, I went absolutely insane with validating user input. However, this isn't always necessary. In the stated task, there are simpler ways to accomplish this. Validating input isn't that important here (in my opinion!) since the input boils down to a few numerical values. This is why I just implemented a simple 0 <= i <= 255 check. In this particular scenario, I don't think anything else is really necessary.

Quote:
And honestly, who does it hurt if I use Regex And I'm interested in regex, not obsessed with it. I'm in a computer programming course to learn programming, so maybe I should also learn other things related, such as regex.
Ah, but the question is whether or not that particular solution is suitable. There are several things to consider:
  • Is the code readable, so you can go back and update it later without trying to re-learn something, or remembering your motivations for given bits of the code?
  • Is the solution expensive? In the magical world of Sourcepawn, this generally isn't something we need to concern ourselves to much with, but it's always something to keep in mind!
  • Will the code I write be understandable to others who wish to edit my work? Will I end up causing irritating people to add me on Steam, or Discord, or spam me with PMs asking me to modify the plugin because they don't understand the code themselves?
  • Do I intend on posting the solution as an example of a good solution on how to perform the given task?

It's great that you're learning regex. The question is whether or not this particular plugin was the best medium in which to do that. Me, I'm still looking for an excuse to learn regex. And git. And SQL. Or literally any other language outside of Pawn. (Every time I try to just read about one of these subjects without a given project in mind, my eyes just gloss over and I lose any interest I ever had...)

Quote:
given the huge difference in our skill levels (yours being much higher than mine)
I disagree. My knowledge is very general with only a few specializations. You put a plugin in front of me that involves gamedata, or particle effects, or databases, or viewmodels, or regex, or anything cool... And I'll stand there with my thumb in my mouth. You're got at least regex on me, now, and probably lots more.

Quote:
text which was edited out
Oh, your code is fine. If it works, it works. Your method choice, however, is questionable, in the opinion of probably most people here, especially when posted to the public forum as an example of how to efficiently preform the task.

You're doing fine. Please don't interpret this criticism as non-constructive.
__________________
ddhoward is offline
404UserNotFound
BANNED
Join Date: Dec 2011
Old 02-25-2018 , 09:15   Re: Snippet: Setting RGB/RGBA values via a command
Reply With Quote #7

I don't know why I took things negatively initially, especially given me saying to leave suggestions for improvement. I think I got too into my own mind with the obsessed with regex post, wondering if it was meant negatively and ended up making myself believe it was and I got defensive.

I do thank you both for the help. It's greatly appreciated, especially as I find I learn better from seeing completed examples of something so I can wrap my head around the "proper" way to do things. It's how I got my start here, picking apart plugins, seeing how they worked, and making them work the way I wanted them to.

Last edited by 404UserNotFound; 02-25-2018 at 09:17.
404UserNotFound is offline
Dr!fter
The Salt Boss
Join Date: Mar 2007
Old 02-28-2018 , 18:49   Re: Snippet: Setting RGB/RGBA values via a command
Reply With Quote #8

In SM 1.10 and 1.9 soon(tm) You can use MatchAll to make the regex even easier. Although, using args is much better. But, since i decided to test with this type of an example... hf

PHP Code:
#pragma newdecls required
 
#include <sourcemod>
#include <regex>
 
public void OnPluginStart()
{
    
int buff[4];
    
    
char test_strings[][] = {"128 233 255""123 232 22 156""126 130 300""257 220 300 100"};
    
    for(
int i 0sizeof(test_strings); i++)
    {
        
int ret CheckRGBA(test_strings[i], buff, (2) ? true false);
        
        if(
ret == 3)
        {
            
PrintToServer("RGB values %i %i %i"buff[0], buff[1], buff[2]);
        }
        else if(
ret == 4)
        {
            
PrintToServer("RGBA values %i %i %i %i"buff[0], buff[1], buff[2], buff[3]);
        }
        else
        {
            
PrintToServer("Invalid RGB(A) values passed");
        }
    }
}

int CheckRGBA(const char [] szRGBint values[4], bool hasAlpha)
{
    
Regex re =  new Regex("\\b([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\b");
    
int ret = -1;
    
int matches re.MatchAll(szRGB);

    if((
matches == && !hasAlpha) || (matches == && hasAlpha))
    {
        
ret matches;
        for(
int i 0matchesi++)
        {
            
char temp[4];
            
re.GetSubString(1tempsizeof(temp), i);
            
values[i] = StringToInt(temp);
        }
    }
    
delete re;
    return 
ret;

And the output

Code:
RGB values 128 233 255
RGBA values 123 232 22 156
Invalid RGB(A) values passed
Invalid RGB(A) values passed
I wouldnt pay much attention to the fiasco in onpluginstart though... im hella lazy.

Last edited by Dr!fter; 02-28-2018 at 18:52. Reason: Fix trademark
Dr!fter is offline
404UserNotFound
BANNED
Join Date: Dec 2011
Old 03-01-2018 , 20:29   Re: Snippet: Setting RGB/RGBA values via a command
Reply With Quote #9

Ooh, very nice.
404UserNotFound is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 08:20.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode