ScriptBase Class
Base class for all scripts, has ScriptHandle accessors and coroutine utilities.
Syntax
Remarks
Requirements
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
Members
See Also: Inherited members from Reflective.
Public Constructors
|
ScriptBase ()
|
Constructor |
Public Properties
Protected Properties
[read-only]
|
AllowedContexts | Reflective.Context . Internal Use Only. Overridden by subclasses to return only those contexts requested which are allowed for that type of script. (Inherited from Reflective.) |
[read-only]
|
CurrentCoroutine | ICoroutine . Gets the ICoroutine interface for the current coroutine. |
[read-only]
|
MaxCoroutines | int . The maximum number of coroutines that a single script can run. |
[read-only]
|
PendingEventCount | int . The number of events currently waiting to be processed. |
[read-only]
|
ReflectiveContexts | Reflective.Context . Override ReflectiveContexts to limit which contexts this Reflective interface is available in when registered with. (Inherited from Reflective.) |
[read-only]
|
ReflectiveName | string . Override ReflectiveName to change which name this class will be registered as in the Reflective system. (Inherited from Reflective.) |
[read-only]
static
|
ScriptEventMessageIdCount | int . Obsolete |
Public Methods
|
AsInterface<TInterface> () : TInterface
Returns a TInterface object if one can be created, null otherwise (Inherited from Reflective.) |
|
|
FullInterface (string) : string
Generates a string which shows all the members which can be reflected. (Inherited from Reflective.) |
|
abstract
|
Init ()
Init() is called after all interfaces have been initialized. |
|
|
Register ()
Register this object to be found with Sansar.Simulation.ScenePrivate.FindReflective(string) (Inherited from Reflective.) |
|
|
Unregister ()
Unregister this object so it will not be found with Sansar.Simulation.ScenePrivate.FindReflective(string) (Inherited from Reflective.) |
|
|
Yield ()
Yield to let other coroutines or events run. |
Protected Methods
Member Details
ScriptBase Constructor
ConstructorSyntax
public ScriptBase ()Remarks
Initializes a new instance of the ScriptBase class.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
CurrentCoroutine Property
Gets the ICoroutine interface for the current coroutine.Syntax
protected ICoroutine CurrentCoroutine { get; }Value
The ICoroutine interface to the currently running coroutine.Remarks
Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
GetAllCoroutines Method
A list of all coroutines for this script.Syntax
protected IReadOnlyList<ICoroutine> GetAllCoroutines ()Returns
A list containing all running or waiting coroutines.Remarks
Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
GetCoroutineCount Method
The total number of coroutines running on this script.Syntax
protected int GetCoroutineCount ()Returns
The total number of coroutines running on this script.Remarks
Includes currently active and waiting coroutines, but not killed coroutines. A new list is created every time it is called with the coroutines at the time of the call. It is possible for coroutines to finish while iterating on the list which will not remove them from the list. Any finished coroutines still in the list will have IsAlive == false.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
Init Method
Init() is called after all interfaces have been initialized.Syntax
[Sansar.Script.NonReflective]
public abstract void Init ()Remarks
Override Init() to set up script subscriptions and callbacks. Any members set before Init is called (such as in a script constructor) may be overwritten before Init is called.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
Lock Method
Use to create a critical section with a using statement, ensuring that no other coroutines or scripts (via Reflective) may enter this code section while one coroutine or script is in it.Syntax
protected IDisposable Lock (object Token)See Also
Parameters
- Token
- The object controlling the lock. Recommended to be a private object member.
Returns
A ScopedLock that holds the lock and will release it in IDisposable.Dispose.Exceptions
Type Reason ArgumentNullException Thrown if Token is null. Remarks
Use with using to create a critical section. If a lock is already held on Token by a different coroutine then this coroutine will wait for the lock to be released before entering the critical section. Lock is conceptually similar to the lock keyword.Example
C# Example private object BalanceLock = new Object(); int Balance = 100; bool Spend(int value) { using (Lock(BalanceLock)) { if (Balance > value) { Balance -= value; return true; } return false; } }Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
Log Property
Gets the script console.Syntax
[Sansar.Script.NonReflective]
public Log Log { protected get; set; }Value
Remarks
Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
MaxCoroutines Property
The maximum number of coroutines that a single script can run.Syntax
protected int MaxCoroutines { get; }Value
The maximum number of coroutines that a single script can run.Remarks
If GetCoroutineCount() == MaxCoroutines, no more coroutines will be started.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
Memory Property
Memory information for the pool this script is in.Syntax
[Sansar.Script.NonReflective]
public Memory Memory { protected get; set; }Value
Remarks
Scripts are pooled by their owner and share memory. Use this object to get events on nearing memory limits as well as get information on memory activity and use.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
PendingEventCount Property
The number of events currently waiting to be processed.Syntax
protected int PendingEventCount { get; }Value
The number of events currently waiting to be processed.Remarks
To remedy a situation of growing pending event count try reducing the number or rate of events the script is receiving or the amount of work done in each event.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
PostScriptEvent Method
Post the event for all scripts.Syntax
Parameters
- message
- The message id used to direct the event.
Remarks
Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
PostScriptEvent Method
Post the event for all scripts.Syntax
Parameters
- message
- The message id used to direct the event.
- data
- The object to be post.
Remarks
Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
PostScriptEvent Method
Post the event for the target script.Syntax
Parameters
- targetScriptId
- The id of the script to sent the event to. To broadcast the message to all subscripted scripts use ScriptBase.PostScriptEvent(string, Reflective).
- message
- The message id used to direct the event.
- data
- The object to be post.
Remarks
Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
PostSimpleScriptEvent Method
Deprecated. Use ScriptBase.PostScriptEvent(ScriptId, string, Reflective)Syntax
[System.Obsolete("Deprecated. Use PostScriptEvent directly instead.", true)]
protected void PostSimpleScriptEvent (string message, object data)See Also
Parameters
- message
- The message id used to direct the event.
- data
- An object to send to scripts subscribed to message.
Remarks
Deprecated. Use ScriptBase.PostScriptEvent(ScriptId, string, Reflective)Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
PostSimpleScriptEvent Method
Deprecated. Use ScriptBase.PostScriptEvent(ScriptId, string, Reflective)Syntax
[System.Obsolete("Deprecated. Use PostScriptEvent directly instead.", true)]
protected void PostSimpleScriptEvent (ScriptId targetScriptId, string message, object data)See Also
Parameters
- targetScriptId
- The id of the script to sent the event to. To broadcast the message to all subscripted scripts use ScriptBase.PostSimpleScriptEvent(string, object).
- message
- The message id used to direct the event.
- data
- An object to send to script targetScriptId if subscribed to message.
Remarks
Deprecated. Use ScriptBase.PostScriptEvent(ScriptId, string, Reflective)Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
ReleaseLock Method
Release a lock if held.Syntax
See Also
Parameters
- Token
- The object controlling the lock. Recommended to be a private object member.
Exceptions
Type Reason ArgumentNullException Thrown if Token is null. Remarks
It is highly recommended to use ScriptBase.Lock(object) instead. This is for advanced use only and can easily create deadlocks that stop scripts from working. Can not be used to release a lock not currently held by this coroutine.Example
C# Example private object BalanceLock = new Object(); int Balance = 100; bool Spend(int value) { WaitForLock(BalanceLock); bool success = false; if (Balance > value) { Balance -= value; success = true; } ReleaseLock(BalanceLock); // Note that any early exit between WaitForLock and ReleaseLock fail to release the lock, creating a deadlock the next time this method is called. // For this reason it is highly recommended to instead do: using (Lock(BalanceLock)) return success; }Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
Script Property
Script handle to this script.Syntax
[Sansar.Script.NonReflective]
public ScriptHandle Script { protected get; set; }Value
An opaque type used by certain API methods.Remarks
Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
ScriptEventMessageIdCount Property
ObsoleteSyntax
[System.Obsolete("No longer used as there is no longer a limited number of message ids. Obsoleted 2018-04.", true)]
protected static int ScriptEventMessageIdCount { get; }Value
Always returns 0Remarks
No longer used as there is no longer a limited number of message ids. Obsoleted 2018-04.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
StartCoroutine Method
Starts a coroutine on the current script.Syntax
Parameters
- coroutine
- The coroutine to run.
- handler
- A callback to know when the coroutine has finished.
Returns
An ICoroutine interface to stop the coroutine or see if it has finished.Remarks
A coroutine can call ScriptBase.WaitFor(Func<Action<Sansar.Script.EventData>,System.UInt64>) to block while waiting for events to return.The following three scripts acccomplish the same goal using event subscriptions and coroutines. Each script will listen for new agents to join the scene and keep track of the agents name and the time it joined. When the agent leaves, its name and the duration of its visit will be reported.
C# Example /* This content is licensed under the terms of the Creative Commons Attribution 4.0 International License. * When using this content, you must: * � Acknowledge that the content is from the Sansar Knowledge Base. * � Include our copyright notice: "� 2017 Linden Research, Inc." * � Indicate that the content is licensed under the Creative Commons Attribution-Share Alike 4.0 International License. * � Include the URL for, or link to, the license summary at https://creativecommons.org/licenses/by-sa/4.0/deed.hi (and, if possible, to the complete license terms at https://creativecommons.org/licenses/by-sa/4.0/legalcode. * For example: * "This work uses content from the Sansar Knowledge Base. � 2017 Linden Research, Inc. Licensed under the Creative Commons Attribution 4.0 International License (license summary available at https://creativecommons.org/licenses/by/4.0/ and complete license terms available at https://creativecommons.org/licenses/by/4.0/legalcode)." */ using System; using Sansar.Script; using Sansar.Simulation; using System.Collections.Generic; public class StarWarsVoiceover : SceneObjectScript { // PUBLIC MEMBERS ------ public SoundResource Sound; [Range(0.0, 60.0)] [DefaultValue(48.0)] public double Loudness_dB; // PRIVATE MEMBERS ------ private float ZeroDBOffset = 48.0f; private RigidBodyComponent RigidBody; private float Relative_Loudness; static private Dictionary<SessionId, PlayHandle> playHandles = new Dictionary<SessionId, PlayHandle>(); private void PlayOnAgent(AgentPrivate agent) { try { SessionId agentId = agent.AgentInfo.SessionId; Stop(agentId); PlaySettings playSettings = PlaySettings.PlayOnce; playSettings.Loudness = Relative_Loudness; if (agent.IsValid) { PlayHandle playHandle = agent.PlaySound(Sound, playSettings); if (playHandle != null) { playHandles.Add(agentId, playHandle); playHandle.OnFinished(() => Stop(agentId)); } } } catch (Exception e) { Log.Write(LogLevel.Warning, "Voiceover", $"Exception {e.GetType().Name} in PlayOnAgent"); } } private void Stop(SessionId id) { try { PlayHandle playing; if (playHandles.TryGetValue(id, out playing)) { playing.Stop(); playHandles.Remove(id); } } catch (Exception e) { Log.Write(LogLevel.Warning, "Voiceover", $"Exception {e.GetType().Name} while stopping a sound"); } } private void OnCollide(CollisionData data) { if (data.Phase == Sansar.Simulation.CollisionEventPhase.TriggerEnter) { try { AgentPrivate agent = ScenePrivate.FindAgent(data.HitComponentId.ObjectId); if (agent != null && agent.IsValid) PlayOnAgent(agent); } catch (Exception e) { // User left with _really_ bad timing, don't worry about it. Log.Write(LogLevel.Warning, "Voiceover", $"Exception {e.GetType().Name} in OnCollide"); } } } private void UserLeft(UserData data) { Stop(data.User); } public override void Init() { ScenePrivate.User.Subscribe(User.RemoveUser, UserLeft); // Collision events are related to the RigidBody component so we must find it. // See if this object has a RigidBodyComponent and grab the first one. if (ObjectPrivate.TryGetFirstComponent(out RigidBody)) { Relative_Loudness = (float)Loudness_dB - ZeroDBOffset; if (RigidBody.IsTriggerVolume()) { // Subscribe to TriggerVolume collisions on our rigid body: our callback (OnCollide) will get called // whenever a character or character vr hand collides with our trigger volume RigidBody.Subscribe(CollisionEventType.Trigger, OnCollide); } } else { // This will write to the region's log files. Only helpful to Linden developers. Log.Write("Couldn't find rigid body!"); } } }Event handlers are useful when there is a well contained bit of code which can get most or all of its state from the Sansar.Script.EventData it receives. In this example, a separate data structure is needed to keep track of the name and join time for each agent since there could be multiple agents in the scene.
C# Example /* This content is licensed under the terms of the Creative Commons Attribution 4.0 International License. * When using this content, you must: * � Acknowledge that the content is from the Sansar Knowledge Base. * � Include our copyright notice: "� 2017 Linden Research, Inc." * � Indicate that the content is licensed under the Creative Commons Attribution-Share Alike 4.0 International License. * � Include the URL for, or link to, the license summary at https://creativecommons.org/licenses/by-sa/4.0/deed.hi (and, if possible, to the complete license terms at https://creativecommons.org/licenses/by-sa/4.0/legalcode. * For example: * "This work uses content from the Sansar Knowledge Base. � 2017 Linden Research, Inc. Licensed under the Creative Commons Attribution 4.0 International License (license summary available at https://creativecommons.org/licenses/by/4.0/ and complete license terms available at https://creativecommons.org/licenses/by/4.0/legalcode)." */ /* Use a coroutine to wait for event callbacks to track visitors to a scene. * For every visitor start a new coroutine to track that visitor's time. */ using System; using Sansar.Script; using Sansar.Simulation; using System.Diagnostics; // This example shows how to use coroutines to track agents entering and leaving the scene public class CoroutineExample : SceneObjectScript { public override void Init() { StartCoroutine(TrackNewUsers); } // Wait for new users and start a new coroutine to time them. private void TrackNewUsers() { // This coroutine will run for the lifetime of the script. while (true) { // Block until an add user event happens UserData data = (UserData)WaitFor(ScenePrivate.User.Subscribe, User.AddUser, SessionId.Invalid); // Start a new coroutine to track the new user // Each coroutine will run cooperatively with the others, this script, and other scripts in the system StartCoroutine(TrackUser, data.User); } } // There will be one instance of this coroutine per active user in the scene private void TrackUser(SessionId userId) { // Track joined time long joined = Stopwatch.GetTimestamp(); // Lookup the name of the agent. This is looked up now since the agent cannot be retrieved after they // leave the scene. string name = ScenePrivate.FindAgent(userId).AgentInfo.Name; // Block until the agent leaves the scene WaitFor(ScenePrivate.User.Subscribe, User.RemoveUser, userId); // Calculate elapsed time and report. TimeSpan elapsed = TimeSpan.FromTicks(Stopwatch.GetTimestamp()-joined); ScenePrivate.Chat.MessageAllUsers(string.Format("{0} was present for {0} seconds", name, elapsed.TotalSeconds)); } }While the amount of code is approximately the same for each, the coroutine version does not require access to any member data, simplifying the tracking by moving all the required information to stack variables.
C# Example /* This content is licensed under the terms of the Creative Commons Attribution 4.0 International License. * When using this content, you must: * � Acknowledge that the content is from the Sansar Knowledge Base. * � Include our copyright notice: "� 2017 Linden Research, Inc." * � Indicate that the content is licensed under the Creative Commons Attribution-Share Alike 4.0 International License. * � Include the URL for, or link to, the license summary at https://creativecommons.org/licenses/by-sa/4.0/deed.hi (and, if possible, to the complete license terms at https://creativecommons.org/licenses/by-sa/4.0/legalcode. * For example: * "This work uses content from the Sansar Knowledge Base. � 2017 Linden Research, Inc. Licensed under the Creative Commons Attribution 4.0 International License (license summary available at https://creativecommons.org/licenses/by/4.0/ and complete license terms available at https://creativecommons.org/licenses/by/4.0/legalcode)." */ /* Use a coroutine as an event callback to easily track visitors to a scene. * Every visitor triggers an AddUser event which will start a coroutine for that visitor. */ using System; using Sansar.Script; using Sansar.Simulation; using System.Diagnostics; // This example shows how to use coroutines and events to track agents entering and leaving the scene public class CoroutineEventExample : SceneObjectScript { public override void Init() { // Subscribe to Add User events // Events can be handled by anonymous methods ScenePrivate.User.Subscribe(User.AddUser, (UserData data) => StartCoroutine(TrackUser, data.User), true); } // There will be one instance of this coroutine per active user in the scene private void TrackUser(SessionId userId) { // Track joined time long joined = Stopwatch.GetTimestamp(); // Lookup the name of the agent. This is looked up now since the agent cannot be retrieved after they // leave the scene. string name = ScenePrivate.FindAgent(userId).AgentInfo.Name; // Block until the agent leaves the scene WaitFor(ScenePrivate.User.Subscribe, User.RemoveUser, userId); // Calculate elapsed time and report. TimeSpan elapsed = TimeSpan.FromTicks(Stopwatch.GetTimestamp()-joined); ScenePrivate.Chat.MessageAllUsers(string.Format("{0} was present for {0} seconds", name, elapsed.TotalSeconds)); } }Coroutines can be mixed with event handlers. This example uses an event handler for the new user events to start a coroutine to watch for the remove user events.
Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
StartCoroutine<T> Generic Method
Starts a coroutine on the current script.Syntax
protected ICoroutine StartCoroutine<T> (Action<T> coroutine, T arg1, Action<OperationCompleteEvent> handler)Type Parameters
- T
- Type of the first parameter to pass to the coroutine when it is run. This can usually be derived from the Action.
Parameters
- coroutine
- The coroutine to run.
- arg1
- First parameter to pass to the coroutine when it is run.
- handler
- A callback to know when the coroutine has finished. Will report Success==false only if an exception was thrown by the coroutine. Message will be the name of the coroutine.
Returns
An ICoroutine interface to stop the coroutine or see if it has finished.Remarks
A coroutine can call ScriptBase.WaitFor(Func<Action<Sansar.Script.EventData>,System.UInt64>) to block while waiting for events to return. See ScriptBase.StartCoroutine(Action, Action<OperationCompleteEvent>) for an extended example.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
StartCoroutine<T,T1> Generic Method
Starts a coroutine on the current script.Syntax
protected ICoroutine StartCoroutine<T, T1> (Action<T, T1> coroutine, T arg1, T1 arg2, Action<OperationCompleteEvent> handler)Type Parameters
- T
- Type of the first parameter to pass to the coroutine when it is run. This can usually be derived from the Action.
- T1
- Type of the second parameter to pass to the coroutine when it is run. This can usually be derived from the Action.
Parameters
- coroutine
- The coroutine to run.
- arg1
- First parameter to pass to the coroutine when it is run.
- arg2
- Second parameter to pass to the coroutine when it is run.
- handler
- A callback to know when the coroutine has finished. Will report Success==false only if an exception was thrown by the coroutine. Message will be the name of the coroutine.
Returns
An ICoroutine interface to stop the coroutine or see if it has finished.Remarks
A coroutine can call ScriptBase.WaitFor(Func<Action<Sansar.Script.EventData>,System.UInt64>) to block while waiting for events to return. See ScriptBase.StartCoroutine(Action, Action<OperationCompleteEvent>) for an extended example.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
StartCoroutine<T,T1,T2> Generic Method
Starts a coroutine on the current script.Syntax
protected ICoroutine StartCoroutine<T, T1, T2> (Action<T, T1, T2> coroutine, T arg1, T1 arg2, T2 arg3, Action<OperationCompleteEvent> handler)Type Parameters
- T
- Type of the first parameter to pass to the coroutine when it is run. This can usually be derived from the Action.
- T1
- Type of the second parameter to pass to the coroutine when it is run. This can usually be derived from the Action.
- T2
- Type of the third parameter to pass to the coroutine when it is run. This can usually be derived from the Action.
Parameters
- coroutine
- The coroutine to run.
- arg1
- First parameter to pass to the coroutine when it is run.
- arg2
- Second parameter to pass to the coroutine when it is run.
- arg3
- Third parameter to pass to the coroutine when it is run.
- handler
- A callback to know when the coroutine has finished. Will report Success==false only if an exception was thrown by the coroutine. Message will be the name of the coroutine.
Returns
An ICoroutine interface to stop the coroutine or see if it has finished.Remarks
A coroutine can call ScriptBase.WaitFor(Func<Action<Sansar.Script.EventData>,System.UInt64>) to block while waiting for events to return. See ScriptBase.StartCoroutine(Action, Action<OperationCompleteEvent>) for an extended example.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
StartCoroutine<T,T1,T2,T3> Generic Method
Starts a coroutine on the current script.Syntax
protected ICoroutine StartCoroutine<T, T1, T2, T3> (Action<T, T1, T2, T3> coroutine, T arg1, T1 arg2, T2 arg3, T3 arg4, Action<OperationCompleteEvent> handler)Type Parameters
- T
- Type of the first parameter to pass to the coroutine when it is run. This can usually be derived from the Action.
- T1
- Type of the second parameter to pass to the coroutine when it is run. This can usually be derived from the Action.
- T2
- Type of the third parameter to pass to the coroutine when it is run. This can usually be derived from the Action.
- T3
- Type of the fourth parameter to pass to the coroutine when it is run. This can usually be derived from the Action.
Parameters
- coroutine
- The coroutine to run.
- arg1
- First parameter to pass to the coroutine when it is run.
- arg2
- Second parameter to pass to the coroutine when it is run.
- arg3
- Third parameter to pass to the coroutine when it is run.
- arg4
- Fourth parameter to pass to the coroutine when it is run.
- handler
- A callback to know when the coroutine has finished. Will report Success==false only if an exception was thrown by the coroutine. Message will be the name of the coroutine.
Returns
An ICoroutine interface to stop the coroutine or see if it has finished.Remarks
A coroutine can call ScriptBase.WaitFor(Func<Action<Sansar.Script.EventData>,System.UInt64>) to block while waiting for events to return. See ScriptBase.StartCoroutine(Action, Action<OperationCompleteEvent>) for an extended example.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
SubscribeToScriptEvent Method
Subscribes to events sent by other scriptsSyntax
protected IEventSubscription SubscribeToScriptEvent (string message, Action<ScriptEventData> callback, bool persistent)Parameters
- message
- The event message to listen for.
- callback
- Handler to call when the event is generated
- persistent
- Set to false if a one time event is desired.
Returns
An IEventSubscription that can be used to Unsubscribe from these script events.Remarks
Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
SubscribeToScriptEvent Method
Subscribes to events sent only by a specific script.Syntax
protected IEventSubscription SubscribeToScriptEvent (ScriptId sourceScriptId, string message, Action<ScriptEventData> callback, bool persistent)Parameters
- sourceScriptId
- Ignore events posted by scripts not matching this id.
- message
- The event message to listen for.
- callback
- Handler to call when the event is generated.
- persistent
- Set to false if a one time event is desired.
Returns
An IEventSubscription that can be used to Unsubscribe from these script events.Remarks
Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
Terminate Method
Terminates this script immediately.Syntax
Parameters
- message
- The message to write to the log.
Remarks
This method does not return.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
Wait Method
Delays execution of the current coroutine for the specified time.Syntax
Parameters
- duration
- The length of time to wait before continuing in seconds.
Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
Wait Method
Delays execution of the current coroutine for the specified time.Syntax
Parameters
- duration
- The length of time to wait before continuing.
Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor Method
Block the current coroutine until otherCoroutine finishes.Syntax
protected void WaitFor (ICoroutine otherCoroutine)Parameters
- otherCoroutine
- The coroutine to wait for.
Remarks
Waiting for the current coroutine, a null coroutine or a coroutine that is not alive will immediately return.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor Method
Use to pause the script until an event happens.Syntax
protected OperationCompleteEvent WaitFor (Action<Action<OperationCompleteEvent>> func)Parameters
- func
- The event-generating API to wait for.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor (Func<Action<EventData>, Action<Sansar.Script.CancelData>,System.Boolean,Sansar.Script.IEventSubscription> func)Parameters
- func
- The event-generating API to wait for.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor (Func<Action<Sansar.Script.EventData>,System.Boolean,Sansar.Script.IEventSubscription> func)Parameters
- func
- The event-generating API to wait for.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor (Func<Action<Sansar.Script.EventData>,System.Boolean,Sansar.Script.IEventSubscription> func, Action run)Parameters
- func
- The event-generating API to wait for.
- run
- An Action to run after subscribing the the event, but before waiting for the event to occurr.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<ARG1> Generic Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor<ARG1> (Func<ARG1, Action<EventData>, Action<Sansar.Script.CancelData>,System.Boolean,Sansar.Script.IEventSubscription> func, ARG1 arg1)Type Parameters
- ARG1
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- arg1
- An argument to func.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<ARG1> Generic Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor<ARG1> (Func<ARG1, Action<Sansar.Script.EventData>,System.Boolean,Sansar.Script.IEventSubscription> func, ARG1 arg1)Type Parameters
- ARG1
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- arg1
- An argument to func.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<ARG1> Generic Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor<ARG1> (Func<ARG1, Action<Sansar.Script.EventData>,System.Boolean,Sansar.Script.IEventSubscription> func, ARG1 arg1, Action run)Type Parameters
- ARG1
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- arg1
- An argument to func.
- run
- An Action to run after subscribing the the event, but before waiting for the event to occurr.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<T1> Generic Method
Use to pause the script until an event happens.Syntax
protected OperationCompleteEvent WaitFor<T1> (Action<T1, Action<OperationCompleteEvent>> func, T1 t1)Type Parameters
- T1
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- t1
- An argument to func.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<ARG1,ARG2> Generic Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor<ARG1, ARG2> (Func<ARG1, ARG2, Action<EventData>, Action<Sansar.Script.CancelData>,System.Boolean,Sansar.Script.IEventSubscription> func, ARG1 arg1, ARG2 arg2)Type Parameters
- ARG1
- The type of the argument to func.
- ARG2
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- arg1
- An argument to func.
- arg2
- An argument to func.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<ARG1,ARG2> Generic Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor<ARG1, ARG2> (Func<ARG1, ARG2, Action<Sansar.Script.EventData>,System.Boolean,Sansar.Script.IEventSubscription> func, ARG1 arg1, ARG2 arg2)Type Parameters
- ARG1
- The type of the argument to func.
- ARG2
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- arg1
- An argument to func.
- arg2
- An argument to func.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<ARG1,ARG2> Generic Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor<ARG1, ARG2> (Func<ARG1, ARG2, Action<Sansar.Script.EventData>,System.Boolean,Sansar.Script.IEventSubscription> func, ARG1 arg1, ARG2 arg2, Action run)Type Parameters
- ARG1
- The type of the argument to func.
- ARG2
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- arg1
- An argument to func.
- arg2
- An argument to func.
- run
- An Action to run after subscribing the the event, but before waiting for the event to occurr.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<T1,T2> Generic Method
Use to pause the script until an event happens.Syntax
protected OperationCompleteEvent WaitFor<T1, T2> (Action<T1, T2, Action<OperationCompleteEvent>> func, T1 t1, T2 t2)Type Parameters
- T1
- The type of the argument to func.
- T2
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- t1
- An argument to func.
- t2
- An argument to func.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<ARG1,ARG2,ARG3> Generic Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor<ARG1, ARG2, ARG3> (Func<ARG1, ARG2, ARG3, Action<EventData>, Action<Sansar.Script.CancelData>,System.Boolean,Sansar.Script.IEventSubscription> func, ARG1 arg1, ARG2 arg2, ARG3 arg3)Type Parameters
- ARG1
- The type of the argument to func.
- ARG2
- The type of the argument to func.
- ARG3
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- arg1
- An argument to func.
- arg2
- An argument to func.
- arg3
- An argument to func.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<ARG1,ARG2,ARG3> Generic Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor<ARG1, ARG2, ARG3> (Func<ARG1, ARG2, ARG3, Action<Sansar.Script.EventData>,System.Boolean,Sansar.Script.IEventSubscription> func, ARG1 arg1, ARG2 arg2, ARG3 arg3)Type Parameters
- ARG1
- The type of the argument to func.
- ARG2
- The type of the argument to func.
- ARG3
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- arg1
- An argument to func.
- arg2
- An argument to func.
- arg3
- An argument to func.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<ARG1,ARG2,ARG3> Generic Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor<ARG1, ARG2, ARG3> (Func<ARG1, ARG2, ARG3, Action<Sansar.Script.EventData>,System.Boolean,Sansar.Script.IEventSubscription> func, ARG1 arg1, ARG2 arg2, ARG3 arg3, Action run)Type Parameters
- ARG1
- The type of the argument to func.
- ARG2
- The type of the argument to func.
- ARG3
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- arg1
- An argument to func.
- arg2
- An argument to func.
- arg3
- An argument to func.
- run
- An Action to run after subscribing the the event, but before waiting for the event to occurr.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<T1,T2,T3> Generic Method
Use to pause the script until an event happens.Syntax
protected OperationCompleteEvent WaitFor<T1, T2, T3> (Action<T1, T2, T3, Action<OperationCompleteEvent>> func, T1 t1, T2 t2, T3 t3)Type Parameters
- T1
- The type of the argument to func.
- T2
- The type of the argument to func.
- T3
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- t1
- An argument to func.
- t2
- An argument to func.
- t3
- An argument to func.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<ARG1,ARG2,ARG3,ARG4> Generic Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor<ARG1, ARG2, ARG3, ARG4> (Func<ARG1, ARG2, ARG3, ARG4, Action<EventData>, Action<Sansar.Script.CancelData>,System.Boolean,Sansar.Script.IEventSubscription> func, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4)Type Parameters
- ARG1
- The type of the argument to func.
- ARG2
- The type of the argument to func.
- ARG3
- The type of the argument to func.
- ARG4
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- arg1
- An argument to func.
- arg2
- An argument to func.
- arg3
- An argument to func.
- arg4
- An argument to func.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<ARG1,ARG2,ARG3,ARG4> Generic Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor<ARG1, ARG2, ARG3, ARG4> (Func<ARG1, ARG2, ARG3, ARG4, Action<Sansar.Script.EventData>,System.Boolean,Sansar.Script.IEventSubscription> func, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4)Type Parameters
- ARG1
- The type of the argument to func.
- ARG2
- The type of the argument to func.
- ARG3
- The type of the argument to func.
- ARG4
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- arg1
- An argument to func.
- arg2
- An argument to func.
- arg3
- An argument to func.
- arg4
- An argument to func.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<ARG1,ARG2,ARG3,ARG4> Generic Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor<ARG1, ARG2, ARG3, ARG4> (Func<ARG1, ARG2, ARG3, ARG4, Action<Sansar.Script.EventData>,System.Boolean,Sansar.Script.IEventSubscription> func, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, Action run)Type Parameters
- ARG1
- The type of the argument to func.
- ARG2
- The type of the argument to func.
- ARG3
- The type of the argument to func.
- ARG4
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- arg1
- An argument to func.
- arg2
- An argument to func.
- arg3
- An argument to func.
- arg4
- An argument to func.
- run
- An Action to run after subscribing the the event, but before waiting for the event to occurr.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<T1,T2,T3,T4> Generic Method
Use to pause the script until an event happens.Syntax
protected OperationCompleteEvent WaitFor<T1, T2, T3, T4> (Action<T1, T2, T3, T4, Action<OperationCompleteEvent>> func, T1 t1, T2 t2, T3 t3, T4 t4)Type Parameters
- T1
- The type of the argument to func.
- T2
- The type of the argument to func.
- T3
- The type of the argument to func.
- T4
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- t1
- An argument to func.
- t2
- An argument to func.
- t3
- An argument to func.
- t4
- An argument to func.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<ARG1,ARG2,ARG3,ARG4,ARG5> Generic Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor<ARG1, ARG2, ARG3, ARG4, ARG5> (Func<ARG1, ARG2, ARG3, ARG4, ARG5, Action<EventData>, Action<Sansar.Script.CancelData>,System.Boolean,Sansar.Script.IEventSubscription> func, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5)Type Parameters
- ARG1
- The type of the argument to func.
- ARG2
- The type of the argument to func.
- ARG3
- The type of the argument to func.
- ARG4
- The type of the argument to func.
- ARG5
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- arg1
- An argument to func.
- arg2
- An argument to func.
- arg3
- An argument to func.
- arg4
- An argument to func.
- arg5
- An argument to func.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<ARG1,ARG2,ARG3,ARG4,ARG5> Generic Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor<ARG1, ARG2, ARG3, ARG4, ARG5> (Func<ARG1, ARG2, ARG3, ARG4, ARG5, Action<Sansar.Script.EventData>,System.Boolean,Sansar.Script.IEventSubscription> func, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5)Type Parameters
- ARG1
- The type of the argument to func.
- ARG2
- The type of the argument to func.
- ARG3
- The type of the argument to func.
- ARG4
- The type of the argument to func.
- ARG5
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- arg1
- An argument to func.
- arg2
- An argument to func.
- arg3
- An argument to func.
- arg4
- An argument to func.
- arg5
- An argument to func.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitFor<ARG1,ARG2,ARG3,ARG4,ARG5> Generic Method
Use to pause the script until an event happens.Syntax
protected EventData WaitFor<ARG1, ARG2, ARG3, ARG4, ARG5> (Func<ARG1, ARG2, ARG3, ARG4, ARG5, Action<Sansar.Script.EventData>,System.Boolean,Sansar.Script.IEventSubscription> func, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, Action run)Type Parameters
- ARG1
- The type of the argument to func.
- ARG2
- The type of the argument to func.
- ARG3
- The type of the argument to func.
- ARG4
- The type of the argument to func.
- ARG5
- The type of the argument to func.
Parameters
- func
- The event-generating API to wait for.
- arg1
- An argument to func.
- arg2
- An argument to func.
- arg3
- An argument to func.
- arg4
- An argument to func.
- arg5
- An argument to func.
- run
- An Action to run after subscribing the the event, but before waiting for the event to occurr.
Returns
An EventData that can be case to type corresponding to the event type of func.Remarks
Throws Sansar.Script.CoroutineException if called from a script's constructor.Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitForLock Method
WaitFor and take a lock on TokenSyntax
See Also
Parameters
- Token
- The object controlling the lock. Recommended to be a private object member.
Exceptions
Type Reason ArgumentNullException Thrown if Token is null. Remarks
It is highly recommended to use ScriptBase.Lock(object) instead. This is for advanced use only and can easily create deadlocks that stop scripts from working. If not paired with ScriptBase.ReleaseLock(object) will create a deadlock preventing this code from being entered.Example
C# Example private object BalanceLock = new Object(); int Balance = 100; bool Spend(int value) { WaitForLock(BalanceLock); bool success = false; if (Balance > value) { Balance -= value; success = true; } ReleaseLock(BalanceLock); // Note that any early exit between WaitForLock and ReleaseLock fail to release the lock, creating a deadlock the next time this method is called. // For this reason it is highly recommended to instead do: using (Lock(BalanceLock)) return success; }Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
WaitForSignal Method
Wait the current coroutine until at least 1 signal is sent to it through the ICoroutine interface.Syntax
protected int WaitForSignal ()Returns
The number of signals received while waiting.Remarks
Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
Yield Method
Yield to let other coroutines or events run.Syntax
[Sansar.Script.NonReflective]
public void Yield ()Remarks
Requirements
Namespace: Sansar.Script
Assembly: Sansar.Script (in Sansar.Script.dll)
Assembly Versions: 1.0.0.0
0 Comments