- Joined
- Dec 12, 2008
- Messages
- 7,385
The Fundamentals of vJass
The purpose of this tutorial
- We have lots of people coming to the hive nowadays who know how to program in languages like
C++, C# or Java, but they don't know the fundamentals of vJass. This leads them to create spaghetti-code.
Convention
globalVariablesAreWrittenLikeThis
localVariablesAreWrittenLikeThis
structMembersAreLikeThis
structMethodsAreLikeThis
CONSTANT_VARIABLES_ARE_WRITTEN_LIKE_THIS
FunctionsAreWrittenLikeThis
Struct names can be written any way you like EXCEPT_LIKE_THIS.
Module names are just like Struct names.
This is not C#, so your create methods shouldn't be called "New", they should be called "create".
The recycling/deallocation method should be called "destroy".
If globals are only one-character long, feel free to call them something like: "W", "Q", "G", etc..
Inside a struct, when you create a local thistype called
this
, when referring to it's members, you could omit the this
.Concepts
Structs in vJass are compiled to create very ugly spaghetti-code.
They generate 2 functions:
JASS:
function Struct_allocate takes nothing returns integer
// allocate some instance
// return it
endmethod
JASS:
function Struct_deallocate takes integer i returns nothing
// useless locals
// useless Double-free protection
// deallocate some instance
// recycle it
endfunction
Showing you the actual code would make you cry..
Here's a way to avoid this.
Make a struct extend an array:
struct myStruct extends array
And add these 3 members:
JASS:
private static integer ic = 0 // instanceCount
private static integer ir = 0 // instanceToRecycle
private thistype rn // Recycle Stack
Allocate like this:
JASS:
local thistype this
// if we aren't going to recycle anything
if 0==ir then
set ic=ic+1 // increase instance count
set this=ic
else
// we have an instance to recycle
// we set the current instance to the recycled one
set this=ir
// we set the recycled instance to the one that proceeds it in the recycle stack
set ir=ir.rn
endif
And Deallocate like this:
JASS:
// Add recycled instance to stack
set .rn=ir
// Make next recycled instance the current one
set ir = this
Some people may argue against this and say that the speed difference is marginal, but I would have to disagree because you'd be losing:
- 2 function calls
- useless double free protection
- useless generated globals (trigger arrays, etc..)
________________________________
Now, let's move on to another concept:
vJass is very slow and function calls are very costly.
If you ever have the oppurtunity to write a one-line function, do it.
JassHelper inlines one-liners.
Also, to increase performance inside functions, follow these rules:
- If you have a function that returns a primitive type (integer, boolean, string), if you're using it more than once in a function, create a local to cache it.
- If you have a function that returns a handle type (unit, player, widget, etc...), if you're using it more than twice in a function, create a local to cache it.
________________________________
Here's another concept:
- When you pass a variable as a parameter, you will be passing a reference to that variable and not the actual variable itself.
In other programming languages such as C++, something like this:
Code:
void setToFive(int i) {
i = 5;
}
would affect the variable i from where it was passed.
In vJass, the passed parameter will be unaffected.
Encapsulation
In vJass, we use the keywords:
readonly
and
private
for encapsulation.
Encapsulation is always important. If a user shouldn't have access to something, make it private.
If you want the user to access something but you don't want him to modify it, make it readonly (only applies to variables).
What to avoid
Most programmers sometimes rely on things like recursion to create algorithms.
Unfortunately, stuff like this is way too slow for Jass.
1- Never use recursion
2- Never iterate over tens of thousands of indicies.
If you want to iterate over tens of thousands of indicies, or even millions of indicies, use TriggerEvaluations:
JASS:
local integer i = 0
loop
exitwhen i>100000
call TriggerEvaluate(SomeTrigger)
endloop
Threads in Warcraft III have an operation limit (Known as the op-limit).
TriggerEvaluate resets this operation limit for the entire thread though.
Scopes vs. Libraries
Most people do this:
- Use scopes for spells
- Use libraries for systems
What I'd recommend is to do this:
- Use libraries everywhere
- Never use scopes
Scopes allow you to make implicit requirements which is a bad programming practice.
________________________________
That's pretty much it.
This is all you need to know about the fundamentals of vJass.
Thank you for reading.
~Magtheridon96