This is not intended to be a complete guide to programming in the Small language. For that, there is a good set of complete documentation available at:
http://www.adminmod.org/index.php?go=help
AdminMod uses a specific version of the small virtual machine.
the version of the small compiler currently available from the
Small website may or may not be fully compatible with Admin Mod usage.
It is strongly reccomended that you use the compiler verison supplied
with the Admin Mod distribution.
The manual for this specific version of the Small compiler is
available for download from the Admin Mod website, not the Small
website. If you find you need it use this
link
The point of this section is to give new and fledgling coders a chance to learn the basics of authoring and compiling plugins for Admin Mod. For information about compiling completed plugins, please take a look at Compiling Admin Mod Scripts 101 in this documentation.
IMPORTANT NOTE: Plugins written to function with Admin Mod therefore use native functions the Admin Mod team provides. Under the terms of the GPL, since the plugins would not work without these native functions, all plugins written for Admin Mod are linked code and are therefore bound by the GPL.
Admin Mod uses a programming language called Small, which is a derivative of the C programming language. So, technically this isn't scripting - it's programming. When you write Small code, you eventually compile it into a binary form. So it's not really scripting. But we call it that. :0)
This section takes for granted that you have some basic programming fundamentals of some sort under your belt.
To declare a variable, you must use the "new" declaration. And, unlike C/C++, You can use this to declare any variable, may it be a string (a lot of characters put together...kind of like a phrase) or a number. So if you wanted to declare a new number, you would use:
new iValue = 0;
If you wanted to declare a string, you would use:
new sName[MAX_DATA_LENGTH];
where MAX_DATA_LENGTH is the number of characters that string can have. It is predefined by Admin Mod to 200. Augmenting the number could cause clients to crash, so playing with this is not recommended.
If you wished to give a value to that String when you define it, simply add its value:
new sName[MAX_DATA_LENGTH] = "Hello
world.";
For those of you who have no idea what is going on, just keep in mind that the one thing that you can ALWAYS edit is whatever is found between quotes. In other words, where a plugin has text output, such as in the "Hello World" example above, you could easily replace the text inside the quotes without to much fear of ruining things. Doing so will not create any errors unless an unknown symbol is used.
Comments are VERY valuable. Something that is "commented out" is completely disregarded by the compiler. This means that you can do absolutely anything in a commented-out area. Authors use this to make comments on their code and explain to other users how the code works. Comments come in two formats:
//
and
/* */
The first type of comment (//) tells the compiler to disregard everything that comes after it in a line. For example, if you wrote:
// new iVal1=0;
new iVal2=0;
the variable iVal1 would NOT be declared. Since "new iVal2=0;" is on a different line, iVal2, on the contrary will be declared.
The second (/* */) comments out everything between /* and */. For instance:
new iVal1=0; /*
new iVal2=0;
*/ new iVal3=0;
the declaration of iVal2 would be disregarded because it is between /* and */ unlike the declaration of iVal1 and iVal2. This type of comment is often used like this:
/*****************************
Admin Mod 2.5
*****************************/
Here, everything is commented out, because when you look closely, this is the same as:
/*
****************************
Admin Mod 2.5
****************************
*/
Note, that /* */ comments CANNOT be nested, i.e. you should not place comment inside of comments. It is safe to have //-style comments in /* */- style commented regions.
Using functions (methods or snippets) is easy. For example, the streq method, which compares two values. Here is the code:
streq(String1,String2,iMaxlength) {
new iNum;
// be careful about how much we check
if (iMaxlength > strlen(String1)) iMaxlength=strlen(String1);
if (iMaxlength > strlen(String2)) iMaxlength=strlen(String2);
for(iNum=0;iNum<iMaxlength;iNum++)
if (String1[iNum]!=String2[iNum]) return 0;
return 1;
}
To use this code, you would write another function:
admin_foo () {
new String1[MAX_DATA_LENGTH] = "Hello world.";
new String2[MAX_DATA_LENGTH] = "Little Bunny Foo Foo";
streq(String1, String2, MAX_DATA_LENGTH);
}
The result would obviously be false (0) because these two strings are different. Had the two been the same, the result would be 1. You could also just add this is inside an existing method, but be careful not to use a variable that might already be in use for something else. All of the methods in Admin Mod are (should be) clearly explained by their authors.
Statements and loops are the basic parts of any computer program. They are the "thinking" portion of a program.
There are 3 basic statements and loops that are used in Admin Mod. They are:
if/else
while
for
The first is quite self explanatory:
if (condition) {
//do something here
}
This means that if the condition is fulfilled than the program will execute what is between the braces. If the condition is not met, the code inside the braces will be ignored. You can add to the if statement with "else"s. For example:
if (iNum == 0 ) {
iNum = 34;
} else {
iNum = 94;
}
If iNum has a value of 0, iNum will be reassigned to 34. If iNum is not 0, then iNum will be assigned to 94. To spice things up, you can add a bunch of if's inside each else. For example:
if ( iNum == 0 ) {
iVal = 2;
} else if ( iNum == 1 ) {
iVal = 3;
} else if ( iNum < 0 ) {
streq( sStringA, sStringB, MAX_DATA_LENGTH);
} else {
iVal = 10;
}
The while loop is the less used loop, but it can be very useful. Its construction is:
while ( condition ) {
//do something
}
The program will keep on doing that something until the condition IS met. For example:
while ( iNum < 0 ) {
say("Please enter a positive number");
}
The program will keep on prompting for a positive number as long as the number imputed is not positive. If the user puts a positive number in on the first try, then the program will ignore the loop right away. The for loop is the most used loop. It is in almost every complicated method or function out there. Its structure is:
for ( starting number; condition; implement number ) {
// do something
}
The program will go through the loop, starting at the starting number, and will do something with it, then restart the whole loop, after implementing the number. An example is necessary for this loop:
for ( iNum = 0; iNum<15; iNum++ ) {
iCount++;
}
This is a simple for loop, just for explanation. The loop will start with iNum=0 (you must have previously defined iNum) and, since iNum=0 is smaller than 15 will add 1 to count (which must have also been defined previously). Since there is nothing left to do inside the loop, iNum will be incremented by 1, and the loop will continue. iNum=1 is smaller than 15, so count is incremented by 1 and since there is nothing else, iNum is incremented. The loop will break when iNum=15, because iNum=15 is not smaller than 15. The result of this loop is obvious, but normally, it is not easy to understand for loops.
There are a multitude of other functions that this small crash-course tutorial will not cover. The most basic will be briefly explained:
break
The break statement ends the loop in which it is nested (inside). No matter the circumstances, if the program comes upon a break statement, the loop will be instantly terminated.
return
The return statement ends the method or function in which it is nested. Like the break statement, it will automatically end all processes that are currently underway. For example:
admin_foo() {
new iNum;
new iCount;
new sString1[MAX_FATA_LENGTH] = “Hello world”;
new sString2[MAX_DATA_LENGTH] = “LittleBunnyFooFoo”;
if ( streq(sString1, sString2, MAX_DATA_LENGTH) ) {
for( iNum = 0; iNum < 15; iNum++ ) {
if ( iNum > 5 ) {
break;
}
iCount++;
}
if ( iCount < 343 ) {
return 1;<
}
if ( iNum == iCount ) {
do_something();
}
}
}
In this example, as soon as, in the for loop, iNum is bigger than 5, the loop will end, without increasing iNum or count. In this far-fetched example, count will always be smaller than 343 so the method admin_foo will end and return a value of 1.
The Small language is a C derivative, C is a popular and very well supported programming language so finding reference materials on the internet or your local library shouldn't be too hard. One very well reccomended book if you are interested is "The C programming Language" by Brian Kernighan and Dennis Ritchie, the creators of the C language. This explains the language how and why it works and is a good reference work for basic C. It is not directly applicable to Small but if you use the small manual and this book with time you should be scripting just about anything you want pretty quickly.
Most programmers prefer one editor or another to work on their scripts, it is perfectly possible to work on your scripts in a very basic editor such as notepad but most people prefer to use an editor which features syntax highlighting. This allows you to more intuitively see the logical structures you are using and lets you use all those pretty colours on your monitor instead of dull old black and white.
Which do you prefer?
this:
convert_string(HLData,Data,MAX_DATA_LENGTH);
convert_string(HLUserName,User,MAX_NAME_LENGTH);
snprintf(Text, MAX_TEXT_LENGTH, "(Admin) %s: %s", User, Data);
for(i=1; i<=maxplayers; i++) {
strinit(Name); //initialize the string before use
if(playerinfo(i,Name,MAX_NAME_LENGTH,SessionID,WONID,Team)==1) {
if(access(ACCESS_CHAT,Name)!=0) {
messageex(Name, Text, print_chat);
} // end inner if
} // end if
} // end for
log(Text);
return PLUGIN_HANDLED;
or this?
convert_string(HLData,Data,MAX_DATA_LENGTH);
convert_string(HLUserName,User,MAX_NAME_LENGTH);
snprintf(Text, MAX_TEXT_LENGTH, "(Admin) %s: %s", User, Data);
for(i=1; i<=maxplayers; i++) {
strinit(Name); //initialize the string before use
if(playerinfo(i,Name,MAX_NAME_LENGTH,SessionID,WONID,Team)==1) {
if(access(ACCESS_CHAT,Name)!=0) {
messageex(Name, Text, print_chat);
} // end inner if
} // end if
} // end for
log(Text);
return PLUGIN_HANDLED;
Of course if you prefer the first option then you already have an editor that you will feel comortable with on your system be it Linux or Windows. If you prefer the second then you may have to download a suitable editor and syntax definition.
If you are using Linux then you will most probably be familiar with either vim or xemacs, both of which provide syntax highlighing for the C/C++ languages. You can use these highlighting schemes with small sucessfully. Gvim is another alternative.
Windows users dont' get a fully featured editor by default, you'll have to download a suitable one yourself. The good news is that there is a lot of choice, most notably UltraEdit, Edit+ and TextPad and OmniPad. Small syntax definitions are known to have been created for each of these editors. There are probably a great many other editors out there that can be used, either with dedicated small support or wth general C/C++ syntax highlighting, the choice is yours.