Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
|
scriptstack [2025/12/15 01:54] jango angelegt |
scriptstack [2025/12/15 02:50] (aktuell) jango [Routines] |
||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| =====Manager===== | =====Manager===== | ||
| - | The scripting system is initialised by creating one or more instances of the ScriptManager class. | + | Das Skriptsystem wird initialisiert, |
| - | Each instance represents a scripting environment where scripts can be loaded and executed. Each | + | |
| - | instance also provides a global variable scope that the scripts can use to share data. | + | |
| - | < | + | < |
| Manager manager = new Manager(); | Manager manager = new Manager(); | ||
| </ | </ | ||
| Zeile 11: | Zeile 9: | ||
| =====Script===== | =====Script===== | ||
| - | Once a script manager is available, scripts can be loaded by creating instances of the Script | + | Sobald ein Manager verfügbar ist, können Skripte durch Erstellen von Instanzen der Klasse "Script" geladen werden. Der Konstruktor des Skriptobjekts benötigt eine Referenz auf den Skriptmanager und einen Namen zur Identifizierung des Skripts. Standardmäßig entspricht dieser Name einem Dateinamen auf der Festplatte. |
| - | The script object' | + | |
| - | the script. By default, this name corresponds to a disk filename. | + | |
| - | < | + | < |
| - | Script script = new Script(scriptManager, "scripts\Wizard.cns"); | + | Script script = new Script(manager, "script.txt"); |
| </ | </ | ||
| - | The script object' | + | Der Konstruktor des Skriptobjekts kompiliert den Skriptquellcode automatisch in Scriptstack-Bytecode. Standardmäßig wird der generierte Bytecode mithilfe eines "Peephole" |
| - | By default, the generated byte code is optimised using a "peephole" | + | |
| - | instructions are added to facilitate mapping of the generated code with the original source. These | + | |
| - | settings may be controlled by setting the ScriptManager' | + | |
| - | OptimiseCode. | + | |
| =====Interpreter===== | =====Interpreter===== | ||
| - | A script object represents only the programming instructions contained within and not its | + | Ein Skriptobjekt repräsentiert lediglich Programmanweisungen (sog Token), nicht aber seinen Ausführungszustand. Um das Skript auszuführen, muss eine Instanz der Klasse " |
| - | execution state. To execute the script, an instance of the ScriptContext class must be created. The | + | |
| - | class' constructor requires a reference to the script to be executed or a reference to one of the | + | |
| - | script' | + | |
| - | context provides execution control, as well as access to the execution state in terms of the variables | + | |
| - | defined during execution, the next statement to be executed and so on. The ScriptContext class | + | |
| - | represents a running instance of a script. Hence, multiple instances of the same script object can be | + | |
| - | executed within the same script manager by creating multiple script contexts referencing the same | + | |
| - | script. | + | |
| - | < | + | < |
| // create a context for the script' | // create a context for the script' | ||
| - | ScriptContext scriptContext | + | Interpreter interpreter |
| // also creates a context for the script' | // also creates a context for the script' | ||
| - | ScriptContext scriptContext | + | Interpreter interpreter |
| // create a context for one of the script' | // create a context for one of the script' | ||
| - | ScriptFunction | + | Function |
| - | ScriptContext scriptContext | + | Interpreter interpreter |
| </ | </ | ||
| - | The script context object allows execution of the referenced script via the three variants of its | + | Das Interpreter-Objekt ermöglicht die Ausführung des referenzierten Skripts über drei Varianten seiner " |
| - | Execute method. These are: execution of scripts for an indefinite amount of time; execution of | + | |
| - | scripts for a given time interval or execution of scripts for up to a maximum number of executed | + | < |
| - | statements. | + | // execute indefinitely, |
| - | The first method variant allows the referenced script function to execute indefinitely or until the | + | interpreter.Interpret(); |
| - | end of the function is reached. If the script contains an infinite loop, this method will block | + | |
| - | indefinitely unless an interrupt is generated. The Execute method returns the total number of | + | |
| - | statements executed since its invocation. | + | |
| - | < | + | |
| - | // execute indefinitely, | + | |
| - | // a script interrupt is generated | + | |
| - | scriptContext.Execute(); | + | |
| </ | </ | ||
| - | The second variant of the Execute method allows the script context to execute up to a given | + | |
| - | maximum number of statements. The script context may break out of execution before the | + | Die zweite Variante der " |
| - | maximum is reached if there are no more statements to process or if an interrupt is generated. | + | |
| - | < | + | < |
| // execute up to a maximumum of 10 statements | // execute up to a maximumum of 10 statements | ||
| - | scriptContext.Execute(10); | + | interpreter.Interpret(10); |
| </ | </ | ||
| - | The third variant of the Execute method accepts a TimeSpan defining the maximum time interval | + | |
| - | allowed for script execution. The method may break out of execution earlier than the given interval | + | Die dritte Variante der " |
| - | if there are no more statements to process or an interrupt is generated. Given a script with a good | + | |
| - | balance of different statements, a possible use of this method is to determine the speed of the | + | < |
| - | scripting system on the target environment | + | |
| - | < | + | |
| // execute for up to 10 milliseconds | // execute for up to 10 milliseconds | ||
| TimeSpan tsInterval = new TimeSpan(0, 0, 0, 0, 10); | TimeSpan tsInterval = new TimeSpan(0, 0, 0, 0, 10); | ||
| - | scriptContext.Execute(tsInterval); | + | interpreter.Interpret(tsInterval); |
| </ | </ | ||
| - | The second and third variants of Execute may be used to implement a virtual multi-threaded | ||
| - | scripting environment. Global variables may be used as semaphores to synchronise concurrently | ||
| - | running scripts. | ||
| - | A script context will normally execute its referenced script function indefinitely, for a given time | + | Ein Interpreter führt seine referenzierte Skriptfunktion normalerweise unbegrenzt für ein bestimmtes Zeitintervall aus, bis eine maximale Anzahl von Anweisungen ausgeführt wurde oder keine weiteren Anweisungen mehr zu verarbeiten sind. In manchen Fällen ist es jedoch wünschenswert, die Ausführung vorzeitig abzubrechen, beispielsweise um die Kontrolle an den Host zurückzugeben, |
| - | interval, until a given maximum number of statements are executed or until there are no more | + | |
| - | statements to process. In some cases it is desirable to break execution prematurely, such as to | + | |
| - | return control to the host when specific statements are executed, or because a script is too | + | |
| - | computationally intensive to execute | + | |
| Conscript provides two ways for generating script interrupts: | Conscript provides two ways for generating script interrupts: | ||
| Zeile 94: | Zeile 65: | ||
| =====Scanner===== | =====Scanner===== | ||
| - | To allow for loading of scripts from other sources -- such as an archive file, network or database -- | + | Um das Laden von Skripten aus anderen Quellen wie Archivdateien, |
| - | a custom script loader class can be developed and bound to the script manager to be used for | + | |
| - | loading the script. The script loader class may be any class that implements the ScriptLoader | + | < |
| - | interface. The loader is used to retrieve the script specified in the Script class constructor and also | + | |
| - | any additional include scripts defined within the original script. | + | |
| - | < | + | |
| // custom script loader class | // custom script loader class | ||
| - | public class MyScriptLoader | + | public class MyScanner |
| - | : ScriptLoader | + | |
| { | { | ||
| - | | + | |
| { | { | ||
| // loader implementation here... | // loader implementation here... | ||
| } | } | ||
| } | } | ||
| + | |||
| // in initialisation code... | // in initialisation code... | ||
| - | ScriptLoader scriptLoader | + | MyScanner scanner |
| - | scriptManager.Loader | + | interpreter.scanner |
| </ | </ | ||
| Zeile 117: | Zeile 85: | ||
| =====Variablen===== | =====Variablen===== | ||
| - | One approach for allowing a script to communicate with or control the host application entails the | + | Eine Möglichkeit, |
| - | application polling the local variables of the associated script context and global variables of the | + | |
| - | associated script manager. It does this by querying the LocalDictionary property of the | + | |
| - | ScriptContext object, the ScriptDictionary property of the Script | + | |
| - | GlobalDicitonary property of the ScriptManager object. | + | |
| - | < | + | < |
| // get value of local variable | // get value of local variable | ||
| - | int iIndex | + | int i = (int)interpreter.LocalMemory["variableName"]; |
| // get value of script variable | // get value of script variable | ||
| - | int iScore | + | int i = (int)script.ScriptMemory["variableName"]; |
| // get value of global variable | // get value of global variable | ||
| - | bool bNewQuest | + | int i = (int)manager.SharedMemory["variableName"]; |
| - | (bool) scriptManager.GlobalDictionary["g_wizardQuestAvailable"]; | + | |
| </ | </ | ||
| Zeile 145: | Zeile 110: | ||
| functions registered beforehand. | functions registered beforehand. | ||
| - | < | + | < |
| - | // define | + | // define |
| - | HostFunctionPrototype hostFunctionPrototype | + | Routine routine |
| - | null, "Player_MoveTo", | + | |
| </ | </ | ||
| Zeile 155: | Zeile 119: | ||
| List< | List< | ||
| - | < | + | < |
| // prepare parameter type list | // prepare parameter type list | ||
| List< | List< | ||
| - | listParameterTypes.Add(typeof(String)); | + | listParameterTypes.Add(typeof(string)); |
| listParameterTypes.Add(typeof(int)); | listParameterTypes.Add(typeof(int)); | ||
| listParameterTypes.Add(typeof(int)); | listParameterTypes.Add(typeof(int)); | ||
| listParameterTypes.Add(typeof(bool)); | listParameterTypes.Add(typeof(bool)); | ||
| - | listParameterTypes.Add(typeof(AssociativeArray)); | + | listParameterTypes.Add(typeof(ArrayList)); |
| - | // define | + | |
| - | HostFunctionPrototype hostFunctionPrototype | + | // define |
| - | | + | Routine routine |
| </ | </ | ||
| Zeile 174: | Zeile 138: | ||
| prototype without a handler: | prototype without a handler: | ||
| - | < | + | < |
| // register host function | // register host function | ||
| - | m_scriptManager.RegisterHostFunction(hostFunctionPrototype); | + | manager.Register(routine); |
| </ | </ | ||
| Zeile 186: | Zeile 150: | ||
| A.I. scripts in a game: | A.I. scripts in a game: | ||
| - | < | + | < |
| - | public class Enemy | + | public class Program |
| - | : HostFunctionHandler | + | |
| { | { | ||
| - | // class implementation | + | |
| - | | + | private |
| - | | + | |
| - | { | + | |
| - | // create script context | + | { |
| - | | + | |
| - | // assign self as host function handler | + | |
| - | | + | } |
| - | } | + | |
| - | // HostFunctionHandler implementation | + | public object |
| - | | + | { |
| - | List< | + | if (functionName |
| - | { | + | { |
| - | // handle random number generator | + | |
| - | if (strFunctionName | + | |
| - | { | + | return; |
| - | int iMin = (int)listParameters[0]; | + | } |
| - | int iMax = (int)listParameters[1]; | + | return null; |
| - | | + | } |
| - | } | + | |
| - | // handle enemy movement | + | } |
| - | else if (strFunctionName == " | + | |
| - | { | + | |
| - | int iDeltaX = (int)listParameters[0]; | + | |
| - | int iDeltaY = (int)listParameters[1]; | + | |
| - | | + | |
| - | } | + | |
| - | // handle enemy direction | + | |
| - | else if (strFunctionName == " | + | |
| - | { | + | |
| - | | + | |
| - | } | + | |
| - | // handle enemy direction flag | + | |
| - | else if (strFunctionName == " | + | |
| - | { | + | |
| - | | + | |
| - | } | + | |
| - | // handle enemy position query | + | |
| - | else if (strFunctionName == " | + | |
| - | { | + | |
| - | | + | |
| - | new AssociativeArray(); | + | |
| - | | + | |
| - | | + | |
| - | return | + | |
| - | } | + | |
| - | // handle player position query | + | |
| - | else if (strFunctionName == " | + | |
| - | { | + | |
| - | | + | |
| - | new AssociativeArray(); | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | } | + | |
| - | // handle enemy fire | + | |
| - | else if (strFunctionName == " | + | |
| - | { | + | |
| - | Image imageSpell = Properties.Resources.EnemySpell; | + | |
| - | int iDamage = m_enemyType == EnemyType.Wizard ? 40 : 20; | + | |
| - | Spell spell = | + | |
| - | new Spell(m_enemies.Room.Spells, | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | return null; | + | |
| - | } | + | |
| - | return null; | + | |
| - | } | + | |
| </ | </ | ||
| Zeile 270: | Zeile 184: | ||
| Alternatively, | Alternatively, | ||
| - | < | + | < |
| // register global Sine function | // register global Sine function | ||
| - | HostFunctionPrototype hostFunctionPrototype | + | Routine routine |
| - | typeof(float), | + | manager.Register(routine, printHandler); |
| - | m_scriptManager.RegisterHostFunction(hostFunctionPrototype, trigHandler); | + | |
| // register global Cosine function | // register global Cosine function | ||
| - | HostFunctionPrototype hostFunctionPrototype | + | routine |
| - | | + | manager.Register(routine, readHandler); |
| - | m_scriptManager.RegisterHostFunction(hostFunctionPrototype, | + | |
| - | // register global Tangent function | + | |
| - | HostFunctionPrototype hostFunctionPrototype = new HostFunctionPrototype( | + | |
| - | typeof(float), | + | |
| - | m_scriptManager.RegisterHostFunction(hostFunctionPrototype, trigHandler); | + | |
| </ | </ | ||
| Zeile 299: | Zeile 208: | ||
| illustrates an alternative implementation of the earlier trigonometry functions example: | illustrates an alternative implementation of the earlier trigonometry functions example: | ||
| - | < | + | < |
| public class TrigonometryModule | public class TrigonometryModule | ||
| : HostModule | : HostModule | ||
| Zeile 358: | Zeile 267: | ||
| Host module registration is very similar to individual function registration: | Host module registration is very similar to individual function registration: | ||
| - | < | + | < |
| // create module instance | // create module instance | ||
| TrigonometryModule trigonometryModule = new TrigonometryModule(); | TrigonometryModule trigonometryModule = new TrigonometryModule(); | ||