Modifiers are not all mutually exclusive, so it may be possible to use multiple modifiers on the same function or method.
The following modifiers can be used on either functions or methods.
Remote functions or methods handle calls from other servers made with the Remote call system. It could go from one server to another, or from a server to the client, but not client to server (which is handled via the Untrusted modifier). A Remote function or method may be called remotely or normally.
remote method ReceiveCall(inputString as string) .
Untrusted works much like the remote modifier, but indicates that a call may be coming in from a client script engine. Because you can never be sure if the client is hacked or not, all functions or methods marked as untrusted have an implicit contract to validate the parameter data and even the fact that they are being called at all. The Untrusted keyword reminds us that input must be carefully verified and may not be trusted.
untrusted function ReceiveClientCall(inputString as string) .
Unique can be used on either functions or methods, but is typically only used on methods. It means a method which exists in one and only one classMethods script. This is useful for methods you do not wish to allow child classes to override (similar to
sealed in C#).
unique method UniqueDoStuff() .
Functions must first be one of the following:
- (no modifier)
- This is a private function, which can only be called within the same script.
- Public functions may be called by any script that is running on the same server process
- Similar to public functions, but live in a shared signature space and have an "expected" signature.
When a script is compiled, the compiler checks all of the called functions in the compiled script, to ensure that they exist, no matter which other files that they may be in.
The compiler also checks that the argument list is correct. For public functions, this is simple because the location of the called function is coded directly into the function call. However, sometimes the location is not specified at compile time, since a
scriptref variable is used instead. In those cases, the name of the script does not have to be specified, but the function that is being called *must* be a shared function (the compiler maintains a list of signatures of all known shared functions). If the function has not already been defined as a shared function, an error will result at compile-time.
By default (with no modifier keyword), a function is private, meaning that it is only available to the other functions that are within the same script.
- Are the default, if no other modifier is used
- Can only be called from within the declaring script, that is to say the private function bar in the script Foo may only be called by other functions in Foo.
- Private functions cannot be called using a scriptref
- A private function of a given name can exist in any number of scripts without conflict. They do not even need the same signature.
function Bar() .
Private functions cannot be called indirectly via a Script Ref. The use of ScriptRefs will be discussed at greater length in the section dealing with shared functions. Because private functions can only be called from within the same script, you do not declare the script to call. So if your test script had a private function that returned a commonly used id, you could do something like this:
function DoTest() myID as ID = GetMyID() .
Note that no script is specified for the call to GetMyID().
Private functions do not share any kind of common namespace; any number of scripts can declare private functions with the same <name> without conflict. Remember however, that a script may still only contain a single function declaration with a given name, regardless of type. Additionally, private functions in different scripts that share the same name can have different signatures. We will discuss more on function namespace and signatures below.
Public functions may be called by other scripts without any particular restrictions.
- Declared by preceding the function declaration with the keyword modifier public;
- Can be called from within the declaring script without specifying the script
- Can be called from other scripts by directly specifying the script
- Cannot be called using a Script Ref
- A public function of a given name can exist in any number of scripts without conflict. They do not even need the same signature.
public function DoSomething(theList references List of String) // function code goes here .
Commonly called utilities in well-known scripts are typically found as public functions.
Any script may call DoSomething() directly, not just the script in which it is declared. It is important to note that the call must be direct; a call that utilizes a Script Ref to the script containing DoSomething will cause the script to fail its compile, giving the message: "Shared function '<name>' not found." This means that to call the function from outside scripts, you must explicitly name the script in which the public function is declared, as shown below:
function TestFunc(theList copies List of String) StringUtils:DoSomething(theList) .
As with private functions, you do not need to specify a script if you are calling a public function that is declared in the same script. So if somewhere else in the StringUtils script, there was a need to call the public function DoSomething(), it could be done simply as:
Because calling a public function from outside the declaring script requires specifying the script by name, public functions do not share a common namespace. As with private functions then, many scripts can all declare public functions of the same name. Also, all those functions can have different signatures.
public function Baz() public function SwordAttack(sword_node as noderef, target_node as noderef)
Shared functions act much like public functions, meaning that they are accessible by any other function. The main difference, is that they live in a shared signature space, and have an "expected" signature. So, for example, a shared function GetNodeName that takes a noderef and returns a string, always has that same signature, in any script which uses it. The statements within the function may be different from script to script, but the signature must be the same.
The compiler maintains a list of all known shared functions, and each time a script with a shared function is compiled, the compiler checks to see if it has the expected signature. If not, an error will result at compile-time.
A shared function:
- Is declared by preceding the function declaration with the keyword modifier shared.
- Can be called from within the declaring script without specifying the script.
- Can be called from other scripts by directly specifying the script.
- Can be called indirectly, via a script reference.
- Can exist in any number of scripts, but all are required to have the exact same signatures.
Shared functions can be called from scripts other than the one in which the function is declared, but must be done via a script reference, not directly.
shared function SubscriptTest() as Boolean // do the subscript's test code here .
To call the function, an outside script would need a reference to declaring script, rather than needing to know the script's identifying name.
where crtr is kindof BaseCreature crtr.subscript:DoSpecial() .
As with private and public functions, you do not need to specify a script reference if you are calling a shared function that is declared in the same script. So if somewhere else in a creature subscript, there was a need to call the shared function DoSpecial(), it could be done simply as:
rather than having to create a script reference and then making a call using it:
myScript as ScriptRef = SYSTEM.EXEC.THISSCRIPT myScript:DoSpecial()
Shared functions are special in that they share a common name and signature space. This means that once a script declares a shared function with a given name and signature, any other script that wishes to declare a shared function with the same name, must also exactly match the signature declared by the function of that name in the original script.
shared function _ReceiveClientSystemNodeList( account as NodeRef of Class _playerAccount, theList as List of String ) // do stuff .
All other area subscripts that wish to utilize this function must declare it in the same way, so that the signatures match. If the signature does not match exactly, the subscript will not compile, giving the error: "This shared function doesn't match other shared functions." To change the signature of a shared function, see Changing signatures.
shared function GetMyName( n as NodeRef ) as String return n.Name . shared function DealDamage(player_node as noderef, damage as integer) .
- See also: External functions
The External modifier is only used in the ExternalFunctions scripts on client and server.
These only have meaning in a class methods script.
In the Replication system for the Seamless world, there are two new modifiers, which indicate whether a method should be called on a proxied node or on its original node. These modifiers exist only on methods and not on functions, and can be used with the unique modifier if necessary.
- ProxyLocal: Means the method is to be executed on the proxied node itself.
- ProxyForward: Means the method is to be executed on the original node in the source GOM, rather than the proxied node. These methods cannot have return values since they are effectively remote calls.