Forum

> > CS2D > General > Lua - commands done in the smart way
Forums overviewCS2D overviewGeneral overviewLog in to reply

English Lua - commands done in the smart way

3 replies
To the start Previous 1 Next To the start

old Lua - commands done in the smart way

Lee
Moderator Off Offline

Quote
I've noticed that of those who frequently tries to script in Lua, a majority of you uses string.sub(text, start, finish) to parse your commands. But here's the dilemma. If you write something like this

1
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:

∗!sayto 2 Hi Player 2

then the command would be like this

1
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

∗!sayto 12 Hi Player 12

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
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.

∗PART 2
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
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

old Re: Lua - commands done in the smart way

RedPillow
User Off Offline

Quote
Is it possible to make a wall, wich can only be destroyed bby certain side?

If you can do this with lua, please give me the code.

If its not possible to do, its my suggestion to next release.
thanks.

old Re: Lua - commands done in the smart way

spartan029
User Off Offline

Quote
Wow that is smart leegao!!! i'll try that! Jonzku777 This is not the place to ask for that kind of lua script!!! Make a thread asking for it, k! Leegao was showcassing an example. And for the wal in the next releese thing NEVER SAY IT AGAIN! If you have a suggestion for DC pm him! He's probably not going to take your advice be cause he does cs2d as a hobby and can quit any time he wants. So dont give him things to do! Get it, Got it, Good!

Admin/mod comment

please don't listen to him. NEVER EVER pm me a suggestion. use the suggestions thread instead. thanks /DC

old Re: Lua - commands done in the smart way

Lee
Moderator Off Offline

Quote
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
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.
To the start Previous 1 Next To the start
Log in to replyGeneral overviewCS2D overviewForums overview