1
2
2
command = text:sub(1, 4) if command == "!say" then ...
and then you want to change it "!echo", now you would be forced to go all of the back to command and change the text:sub(1, 4) to text:sub(1, 5). Well, that's not too bad, you think. But now, let's say that we have a !sayto command that goes like this:

then the command would be like this
1
2
3
2
3
if text:sub(1, 6) == "!sayto" then 	local player = text:sub(8, 8) 	local text = text:sub(10)
This is where it begins to become a nightmare for you. Not only do you have to remember where each of the parts that you need has to be, but you'll also have no flexibility. Say that you want to use this

what would happen with the above code would be that Player 12 will not get the message, Player one will, and it will say "2 Hi Player 12". So then you'll have to go back and change everything yet again
1
if tonumber(text:sub(9,9)) then player = player .. text:sub(9, 9) end
This is still not enough because now it will tell Player 12 "i Player 12"
These headaches aren't necessary at all.
Let's say that there's a function that can split a string by its spaces, let's call this function string.split(), and another one that let's that there's a join function that takes a table and turns it into text. Then the above code would all come down to 4 lines that you would never have to change.
1
2
3
4
2
3
4
command = text:split() if command[1] == "!sayto" then 	local player = tonumber(command[2]) 	local text = string.join(command, 3, " ")
Easier? This should be, you shouldn't even have to think to get this done. But why stop there? If you must do this to every command that you write, wouldn't it be easier to write a function called args that takes the text, and the number of arguments it has, and splits it accordingly?
It's all about looking at patterns and taking out stuff that have already been written before. I hope this has been helpful to those of you struggling to get commands written.

also, for those of you interested, the function to split strings via spaces is included in http://www.unrealsoftware.de/files_show.php?file=1054 in both string.split() and string.qsplit()
For the next part in this tutorial - Refactoring the command parser.
There's an inherent pattern in most of the commands, they usually look something like this
CommandName [space] Argument1 [space] Argument2 [space] ... ArgumentN
In most cases, we know what N is, so in this case, we should by logic be able to write a function, which we should call args(), that takes in the text to be parsed, the number of arguments there are, or the namespace to be given to each argument inside the returned table.
This is where Lua's tables do its magic.
*Note: This will overwrite Lua's default args Global, but since args is only useful at the begining of the program, if you really need to use it, do it before you initialize this function
Dependencies: http://amx2d.co.cc/viewtopic.php?f=12&t=83
Download the attachment: (1Kb) http://amx2d.co.cc/download/file.php?id=7
The basic idea is that in a given setting, using split only will also create some problems. For example, if you want to use split on "sayto 3 Hello Player", and you use cmd[1], cmd[2], and cmd[3], you would only get "sayto", "3", "Hello". The solution for this lies inside of args
say we do args("sayto 3 Hello Player", 3)
first, we just split the text into its components
n = 3
args = {"sayto", "3", "Hello", "Player"}
Here, we need to recognize that we must take only 2 or n-1 elements from the splitted string because we want the 3rd element to be "Hello Player", not "Hello" only. So once we iterate through 1 to n-1 elements and add them onto the return table, we will need a way to join the remaining elements. Luckily there's an easy solution for that
1
2
2
local str = "" for i = n, #args do str = str .. args[i] end
insert str into the return table and now you have it, the table [ret] will look like
ret = {"sayto", "3", "Hello World"}
Becareful though, there are still certain condtions you must check for before you can adequately get this to work, I have a version already written and packaged with all of the needed dependencies as well as the code highlighted at http://amx2d.co.cc/viewtopic.php?f=12&t=83 . Contact me if you have further questions.
edited 1×, last 18.04.09 05:59:15 pm