Sve tutorial

See also: Timers · Events · Foreach loop · Naming conventions · Svefiles and include · Command blocks

Sve language

Variables and data types

There are five important datatypes in Sve: number, string, bool, table and function. Rare datatypes nfunction and userdata are not discussed in this document.

Number is floating pointer datatype and equivalent to Java's double. Strings are in UTF-8 format. Boolean constants are true and false. nil is false.

Tables are complex data structures and have many features. They are basically hash maps. Keys are always strings, if a number is given it is converted to a string. Word array is used as a synonym to table.

Constants

Number constants

Number constants are in decimal format. They can contain decimals (0.435) or be in sciencific format (like 0.435e34). Infinity and NaN are number constants.

String constants

Strings are in UTF-8 format. They can contain escaped characters Escape character is \.

One word string can also be in the key format: :key.

"A normal string"

:key_format

"A" == :A

Table values

Table values can be either in table format or list format.

# table format
tbl = { key = value, key1 = value2 }

# list format
list = [value1, value2]

In list format keys are given to variables. Value 1 gets key 0. Value 2 gets key 1.

Boolean constants and the nil constant

Boolean constants are true and false. The nil constant, nil, is a equivalent to null in Java or Javascript.

Declaring variables

In Sve, undefined variables are an error. To define a variable a value must be assigned to it.

var = value

i = 3
msg = "Hello world!"
car = { topspeed=3, color=:red }

Inside functions local keyword should be used when declaring new variables. If there is a variable of the same name on the top level, a value is assigned to it instead of declaring a new variable.

def: myfunction() {
    local msg = "Hello world!"
    # ...
}

# without local keyword
msg = nil
def: setmsg(newmsg) {
    msg = newmsg
}

Number increment and decrement statements

Shortcut syntaxes variable++ and variable-- increment and decrement number variables by one. Expression variable++ returns the original value and + +variable the incremented value.

Table accessing and modifying expressions

table[key] is the primary way to get a value from a table. Shortcut syntax table.key can be used and is equivalent to table["key"] (similar to one in Lua).

Modifying a table is similar to modifying a variable.

tbl = { a=1, b=2 }
tbl.a = 2
tbl["b"] = 3

Statements and control structures

Semicolons

Semicolons are not required, but can be used in order to prevent ambiguities. Programmer can decided whether to use semicolons or not.

Following ambiguities are solved using semicolons:

# a = b(c+d)->e
a = b
;(c+d)->e

# a = $$.b = c
a = $;
$.b = c

Blocks

A block starts with { and ends with }. A block is considered to be a single statement.

If

if: condition {
    # action 1
} else: {
    # action 2
}

If condition evaluates to true, the first action is executed. Otherwise the second action is executed. Else-block is optional.

While and For

Code inside a while loop is executed as long as the condition is true.

while: condition {
    # code
}

Code inside a for loop is executed as long as the condition is true. Initialization is executed before the loop and incrementing is executed every time after the code is executed.

for: initialization, condition, incrementation {
    # code
}

Example:

for: local i = 0, i < 10, i++ {
    print(i)
}

Functions

Functions are first class values in Sve. All functions are anonymous and can be assigned to a variables.

A "named" function is declared using a shortcut syntax.

def: function_name(parameters) {
    # code
}

Which is equivalent to:

function_name = def(parameters) {
    # code
}

A value is returned using return keyword.

def: squaresum(value1, value2) {
    return value1*value1 + value2*value2
}

A shortcut syntax can be used for one line math functions.

def: squaresum(v1, v2) = v1*v1 + v2*v2

Function calling

There are three function calling syntaxes. First, parentheses. function(args). Second, ::-operator: function::arg, which is handy for printing text. Third, arrow operator: arg1->function(rest_of_arguments). Arrow resembles method calling and is sometimes used with conversion functions. 20->ticks returns value of 20 seconds in ticks.

print("hello")
print::"hello"
"hello"->print

tell(@m, "hello")
@m->tell("hello")

a=[1,2,3]
len(a)
a->len

Important Sve functions

FunctionTypeDescription
keys(tbl)table -> tableReturns an array which contains all keys of table tbl.
len(arr)table -> numberReturns the number of elements with a numerical key in array arr. To get the size of a table, use len(tbl->keys).
rnd(n)number -> numberCreates a random number in range 0..n-1
type(obj)any -> stringReturns the name of the type of obj. (either bool, function, nil, number or table)

Sve function documentation

There are many sve functions, you can list all sve function help texts using function allhelp (from chat /sve allhelp()). A single help text can be viewed using help function (from chat /sve help("function_name")).

Synthetic variables

Scope variables

In sve, scopes are tables that are used to store variables. There are two important scope variables: the global scope ($) and the local scope ($$). The global scope contains all variables that are declared at the top level. Not inside any block. The local scope contains all variables in the local (current) scope and all parent scopes including the global scope.

hello = "hello world"
print($["hello"])  # -> "hello world" hello is declared at the top level
print($$["hello"]) # -> "hello world" the local scope is the global scope in top level

i = 1
{
    local i = 3 # local keyword is used to create a new variable, it is not required at the top level

    print($["i"])  # -> 1
    print($$["i"]) # -> 3
}

Modifying scopes

Scopes can be modified using these functions. Remember, scopes are tables and these function work with both tables and scopes.

FunctionTypeDescription
define(scope, index, value)table, string, any ->Creates a new variable or modifies an existing in a specific scope. Super scopes are ignored. Can be compared to the local keyword.
undefine(table, index)table, string ->Removes an entry from a table. Works with scopes too.
defined(table, index)table, string -> boolReturns true if table contains an index. Works with scopes too.
setsup(scope, scope)table, table -> tableSets the super scope of a scope.
getsup(scope)table -> tableReturns the super scope of a scope.
setpt(scope, scope)table, table -> tableSets the prototype scope of a scope.
getpt(scope)table -> tableReturns the prototype scope of a scope.
setptf(scope, function)table, function ->Sets the prototype/index function of a scope.
getptf(scope)table -> functionReturns the prototype/index function of a scope.
setls(function, scope)function, table ->Sets function declaration scope.
getls(function)function -> tableGets the declaration scope of a function.

Every table (and scope) has a super table. If an index is not found from the table, it is assumed to be in the super table. A prototype table is like the super table, except that it is read-only.

tbl = {}
sup = {a=1, b=2}
setsup(tbl, sup)

print(tbl.a) # -> 1
print(sup.a) # -> 1
print(defined(tbl, "a")) # -> false

tbl.a = 2
print(tbl.a) # -> 2
print(sup.a) # -> 2
print(defined(tbl, "a")) # -> false

# ,

tbl = {}
pt = {a=1, b=2}
setpt(tbl, pt)

print(tbl.a) # -> 1
print(pt.a) # -> 1
print(defined(tbl, "a")) # -> false

tbl.a = 2
print(tbl.a) # -> 2
print(pt.a) # -> 1
print(defined(tbl, "a")) # -> true

Prototype function is called if an index is not found from super or prototype table. A prototype function takes the index as an argument ant returns it's value. A table which has a prototype function can't trigger an index not found exception.

Synthetic parameters

Generated parameters begin with character $. They can be accessed using scope variables.

VariableUsing scope variableTypeDescription
$args$$["$args"]tableAn array of arguments
$parent$$["$parent"]scopeThe scope which function is called from
$obj$$["$obj"]anyThe object which contains the function, available only when function is called in style obj.function() in which case it contains obj

$parent can be used to modify caller's environment. For example, this removes $-characters from synthetic parameters:

def: removedollar {
    local parent = $$["$parent"]
    define(parent, "parent", parent["$parent"]) # define-function is used in place of the local-keyword when modifying scopes
    define(parent, "args", parent["$args"])
    if: defined(parent, "$obj") # $obj does not exist if function is called in a wrong way
        define(parent, "obj", parent["$obj"])
}

def: printsynthetics {
    removedollar()
    print::keys(parent) # scope variable should not be printed
    print::args
    if: defined($$, "obj") print::obj
}

{
    local i = 1
    printsynthetics()
}

Sve for Bukkit

Built-in functions

FunctionTypeDescription
broadcast(msg)string -> nilBroadcasts a message
print(msg)string -> nilSends a message to all players
tell(player, msg)player or string, string -> nilSends a message to a player
give(player, itemid)player or string, number -> nilGives an item to the player
exec(player, cmd)player or string, string -> numberExecutes the command as a player
system(cmd)string -> nilExecutes the command
hasperm(player, perm)player or string, string -> booleanDoes a player have a permission?
players()( ) -> table(player)Current players on the server
worlds()( ) -> table(world)Current worlds
location(x, y, z, world)number, number, number, world -> locationCreates a new org.bukkit.Location object
vector(x, y, z)number, number, number -> vectorCreates a new org.bukkit.util.Vector object
registereventhandler(event, handler)string, function -> nilRegisters an event handler
getServer()->serverReturns the server (org.bukkit.Bukkit)

Minecraft integration

Variables @m, @a and @w and related functions players() and worlds() are used to get the current player (@m), all players on the server (@a) and all worlds (@w). @m is a players object, and @a and @w are arrays.

Methods of Java objects can be accessed. For example, @m is a CraftPlayer object and contains all methods from org.bukkit.entity.Player. A list of these methods is found from bukkit api documentation (here).

As Sve is a typeless language and does not support method overloading, method names contain also types of the parameters. Method sendMessage(String) is called in sve code sendMessage_String. To send a message to a player: @m.sendMessage_String("msg"). If method is not overloaded, it can be used also without type information.

if: len(@a) != 0 {
    local player = @a[rnd(@a->len)] # random player
    if: !player.isOnGround() {
        player.sendMessage_String("Hey, do you fly?!")
    }
}

Java Interface functions

getClass(name) returns a java.lang.class object. getClass("java.lang.Object") returns the same object as java.lang.Object.class in java.

static(name) returns a table that contains all static fields (including enum constants) of a class. static("java.lang.Math") returns a table that contains constants E and PI.

It is recommended to "import" enums at the begin of a svefile:

material = static("org.bukkit.Material")

# ...

block_material = material.STONE

Comments

Posts Quoted:
Reply
Clear All Quotes