### Install VRCOSC Module Templates Source: https://github.com/volcanicarts/vrcosc/wiki/Module-Creation Use the .NET CLI to install the official project templates for creating new modules. ```bash dotnet new install VolcanicArts.VRCOSC.Templates ``` -------------------------------- ### Create a New Module Project Source: https://github.com/volcanicarts/vrcosc/wiki/Module-Creation Generate a new module project structure using the installed template. ```bash dotnet new VRCOSCModuleDefault -n MODULENAME ``` -------------------------------- ### Parameter Creation Source: https://github.com/volcanicarts/vrcosc/wiki/Module-Creation Examples of creating different types of OSC parameters with their modes, names, and descriptions. ```APIDOC ## Parameter Creation ### Description This section demonstrates how to create OSC parameters using the `CreateParameter` method. Parameters require an Enum as a key, followed by the parameter mode, the parameter's name, and a description. ### Method `CreateParameter(Enum key, ParameterMode mode, string name, string description)` ### Parameters - **T** (type) - The data type of the parameter (e.g., bool, float, int). - **key** (Enum) - An Enum value representing the parameter identifier (e.g., `MediaParameter.Play`). - **mode** (ParameterMode) - The mode of the parameter (e.g., `ParameterMode.ReadWrite`, `ParameterMode.Read`). - **name** (string) - The OSC path for the parameter (e.g., `"VRCOSC/Media/Play"`). - **description** (string) - A human-readable description of the parameter. ### Request Example ```c# CreateParameter(MediaParameter.Play, ParameterMode.ReadWrite, @"VRCOSC/Media/Play", "Play/Pause", @"True for playing. False for paused"); CreateParameter(MediaParameter.Volume, ParameterMode.ReadWrite, @"VRCOSC/Media/Volume", "Volume", @"The volume of the process that is controlling the media"); CreateParameter(MediaParameter.Muted, ParameterMode.ReadWrite, @"VRCOSC/Media/Muted", "Muted", @"True to mute. False to unmute"); CreateParameter(MediaParameter.Repeat, ParameterMode.ReadWrite, @"VRCOSC/Media/Repeat", "Repeat", @"0 for disabled. 1 for single. 2 for list"); CreateParameter(MediaParameter.Shuffle, ParameterMode.ReadWrite, @"VRCOSC/Media/Shuffle", "Shuffle", @"True for enabled. False for disabled"); CreateParameter(MediaParameter.Next, ParameterMode.Read, @"VRCOSC/Media/Next", "Next", @"Becoming true causes the next track to play"); CreateParameter(MediaParameter.Previous, ParameterMode.Read, @"VRCOSC/Media/Previous", "Previous", @"Becoming true causes the previous track to play"); ``` ``` -------------------------------- ### Install VRCOSC Module Template Source: https://context7.com/volcanicarts/vrcosc/llms.txt Use the dotnet CLI to install the VRCOSC template and scaffold new module projects. ```bash # Install the VRCOSC module template dotnet new install VolcanicArts.VRCOSC.Templates # Create a new module project dotnet new VRCOSCModuleDefault -n MyCustomModule # The template creates a properly configured project with: # - Correct assembly references # - Build output to VRCOSC's assemblies folder # - Module class skeleton ``` -------------------------------- ### Implement VRChat Player Action Nodes Source: https://context7.com/volcanicarts/vrcosc/llms.txt Built-in node examples for controlling VRChat player states like muting, jumping, and avatar switching. ```csharp // Example Pulse flow: On Start -> Mute Toggle -> Jump [Node("Mute Set", "VRChat/Player/Actions")] public sealed class PlayerMuteSetNode : Node, IFlowInput { public FlowContinuation Next = new("Next"); public ValueInput Muted = new(); protected override async Task Process(PulseContext c) { if (Muted.Read(c)) c.GetPlayer().Mute(); else c.GetPlayer().UnMute(); await Next.Execute(c); } } [Node("Jump", "VRChat/Player/Actions")] public sealed class PlayerJumpNode : Node, IFlowInput { public FlowContinuation Next = new("Next"); protected override async Task Process(PulseContext c) { c.GetPlayer().Jump(); await Next.Execute(c); } } [Node("Change Avatar", "VRChat/Player/Actions")] public sealed class PlayerChangeAvatarNode : Node, IFlowInput { public FlowContinuation Next = new("Next"); public ValueInput AvatarId = new("Avatar Id"); protected override async Task Process(PulseContext c) { var avatarId = AvatarId.Read(c); if (!string.IsNullOrEmpty(avatarId)) AppManager.GetInstance().VRChatOscClient.Send("/avatar/change", avatarId); await Next.Execute(c); } } ``` -------------------------------- ### Implement Module Settings Source: https://context7.com/volcanicarts/vrcosc/llms.txt Demonstrates various UI component types for user-configurable settings and how to retrieve them at runtime. Settings are defined in OnPreLoad and accessed via GetSettingValue or GetSetting. ```csharp protected override void OnPreLoad() { // Boolean toggle CreateToggle(MySetting.Enabled, "Enabled", "Whether this feature is enabled", true); // Text input for different types CreateTextBox(MySetting.Username, "Username", "Your username", ""); CreateTextBox(MySetting.Port, "Port Number", "The port to connect on", 9000); CreateTextBox(MySetting.Threshold, "Threshold", "The threshold value", 0.5f); // Password field (masked input) CreatePasswordTextBox(MySetting.Password, "Password", "Your secret password", ""); // Slider with range CreateSlider(MySetting.Volume, "Volume", "Volume level", 50, 0, 100, 5); CreateSlider(MySetting.Sensitivity, "Sensitivity", "Detection sensitivity", 0.5f, 0.0f, 1.0f, 0.1f); // Dropdown from enum CreateDropdown(MySetting.Mode, "Mode", "Select operation mode", MyModeEnum.Normal); // Date/time picker CreateDateTime(MySetting.ScheduledTime, "Scheduled Time", "When to trigger", DateTimeOffset.Now); // List of values CreateTextBoxList(MySetting.Keywords, "Keywords", "List of keywords to monitor", new[] { "hello", "goodbye" }); CreateTextBoxList(MySetting.Values, "Values", "List of numeric values", new[] { 1, 2, 3 }); // Group related settings in UI CreateGroup("Connection", "Network connection settings", MySetting.Username, MySetting.Port); CreateGroup("Behavior", "Module behavior settings", MySetting.Mode, MySetting.Threshold); } // Access settings at runtime [ModuleUpdate(ModuleUpdateMode.Custom, deltaMilliseconds: 100)] private void Update() { if (!GetSettingValue(MySetting.Enabled)) return; var threshold = GetSettingValue(MySetting.Threshold); var keywords = GetSetting(MySetting.Keywords).Attribute.ToList(); // Process using settings... } ``` -------------------------------- ### Create a Basic Module Source: https://context7.com/volcanicarts/vrcosc/llms.txt Defines a custom module by inheriting from the Module base class and implementing lifecycle methods. Use attributes for metadata and OnPreLoad to register settings and parameters. ```csharp using VRCOSC.App.SDK.Modules; using VRCOSC.App.SDK.Parameters; [ModuleTitle("My Custom Module")] [ModuleDescription("A short description of what my module does", "A longer, more detailed description")] [ModuleType(ModuleType.Generic)] [ModuleInfo("https://example.com/docs")] public class MyCustomModule : Module { private enum MySetting { EnableFeature, UpdateInterval, ApiKey } private enum MyParameter { OutputValue, InputTrigger } protected override void OnPreLoad() { // Create settings CreateToggle(MySetting.EnableFeature, "Enable Feature", "Enables the main feature of this module", true); CreateTextBox(MySetting.UpdateInterval, "Update Interval", "How often to update (in milliseconds)", 1000); CreatePasswordTextBox(MySetting.ApiKey, "API Key", "Your API key for the service", ""); // Register parameters for VRChat communication RegisterParameter(MyParameter.OutputValue, "VRCOSC/MyModule/Output", ParameterMode.Write, "Output", "The output value sent to VRChat"); RegisterParameter(MyParameter.InputTrigger, "VRCOSC/MyModule/Trigger", ParameterMode.Read, "Trigger", "Receives trigger events from VRChat"); } protected override Task OnModuleStart() { Log("Module started!"); return Task.FromResult(true); } protected override Task OnModuleStop() { Log("Module stopped!"); return Task.CompletedTask; } } ``` -------------------------------- ### Define Module Parameters Source: https://github.com/volcanicarts/vrcosc/wiki/Module-Creation Implement the CreateAttributes method to register parameters for VRChat communication. ```c# public override void CreateAttributes() { CreateParameter(HeartrateParameter.Enabled, ParameterMode.Write, "VRCOSC/Heartrate/Enabled", "Enabled", "Whether this module is attempting to emit values"); CreateParameter(HeartrateParameter.Normalised, ParameterMode.Write, "VRCOSC/Heartrate/Normalised", "Normalised", "The heartrate value normalised to 240bpm"); CreateParameter(HeartrateParameter.Units, ParameterMode.Write, "VRCOSC/Heartrate/Units", "Units", "The units digit 0-9 mapped to a float"); CreateParameter(HeartrateParameter.Tens, ParameterMode.Write, "VRCOSC/Heartrate/Tens", "Tens", "The tens digit 0-9 mapped to a float"); CreateParameter(HeartrateParameter.Hundreds, ParameterMode.Write, "VRCOSC/Heartrate/Hundreds", "Hundreds", "The hundreds digit 0-9 mapped to a float"); } ``` -------------------------------- ### Implement ChatBox Integration in a Module Source: https://context7.com/volcanicarts/vrcosc/llms.txt Defines variables, states, and events within a module to interact with the ChatBox system. Variables must be created before states and events. ```csharp public class MediaModule : Module { private enum MediaState { Playing, Paused } private enum MediaEvent { NowPlaying } private enum MediaVariable { Title, Artist, Progress } protected override void OnPostLoad() { // Create variables FIRST (before states/events) var titleVar = CreateVariable(MediaVariable.Title, "Title")!; var artistVar = CreateVariable(MediaVariable.Artist, "Artist")!; CreateVariable(MediaVariable.Progress, "Progress"); // Create states with default format and variables CreateState(MediaState.Playing, "Playing", "Now Playing: {0} - {1}", new[] { titleVar, artistVar }); CreateState(MediaState.Paused, "Paused", "Paused"); // Create events with duration and behavior CreateEvent(MediaEvent.NowPlaying, "Now Playing", "Now Playing: {0}", new[] { titleVar }, defaultShowTyping: false, defaultLength: 5, defaultBehaviour: ClipEventBehaviour.Override); } protected override Task OnModuleStart() { // IMPORTANT: Set initial state on start ChangeState(MediaState.Paused); return Task.FromResult(true); } [ModuleUpdate(ModuleUpdateMode.ChatBox)] private void UpdateChatBox() { // Update variable values SetVariableValue(MediaVariable.Title, currentTrack.Title); SetVariableValue(MediaVariable.Artist, currentTrack.Artist); SetVariableValue(MediaVariable.Progress, playbackProgress); // Change state based on playback if (isPlaying) ChangeState(MediaState.Playing); else ChangeState(MediaState.Paused); } private void OnTrackChanged() { // Trigger event when track changes TriggerEvent(MediaEvent.NowPlaying); } } ``` -------------------------------- ### Incoming Parameter Handling Source: https://github.com/volcanicarts/vrcosc/wiki/Module-Creation Methods for handling incoming OSC parameters, including a general handler and module-specific handlers. ```APIDOC ## Incoming Parameter Handling ### Description Modules can handle incoming OSC parameters by overriding specific methods. `OnAnyParameterReceived` is a general handler, while `OnAvatarModuleReceived` and `OnWorldModuleReceived` are for module-specific parameters. ### Methods - `OnAnyParameterReceived(ReceivedParameter parameter)`: A general handler for any received parameter. Use with caution as it can receive any avatar parameter. - `OnAvatarModuleReceived(AvatarParameter parameter)`: Specific handler for avatar module parameters. - `OnWorldModuleReceived(WorldParameter parameter)`: Specific handler for world module parameters. ### Usage Notes - `OnAnyParameterReceived` should be used sparingly to avoid performance issues and unintended behavior. - The Counter module is an example of a viable use case for `OnAnyParameterReceived`. ### Request Example ```c# protected virtual void OnAnyParameterReceived(ReceivedParameter parameter) { } // AvatarModule only protected virtual void OnAvatarModuleReceived(AvatarParameter parameter) { } // WorldModule only protected virtual void OnWorldModuleReceived(WorldParameter parameter) { } ``` ``` -------------------------------- ### Registering OSC Parameters Source: https://github.com/volcanicarts/vrcosc/wiki/Module-Creation Use CreateParameter to define module parameters with specific types, modes, and OSC addresses. ```c# CreateParameter(MediaParameter.Play, ParameterMode.ReadWrite, @"VRCOSC/Media/Play", "Play/Pause", @"True for playing. False for paused"); CreateParameter(MediaParameter.Volume, ParameterMode.ReadWrite, @"VRCOSC/Media/Volume", "Volume", @"The volume of the process that is controlling the media"); CreateParameter(MediaParameter.Muted, ParameterMode.ReadWrite, @"VRCOSC/Media/Muted", "Muted", @"True to mute. False to unmute"); CreateParameter(MediaParameter.Repeat, ParameterMode.ReadWrite, @"VRCOSC/Media/Repeat", "Repeat", @"0 for disabled. 1 for single. 2 for list"); CreateParameter(MediaParameter.Shuffle, ParameterMode.ReadWrite, @"VRCOSC/Media/Shuffle", "Shuffle", @"True for enabled. False for disabled"); CreateParameter(MediaParameter.Next, ParameterMode.Read, @"VRCOSC/Media/Next", "Next", @"Becoming true causes the next track to play"); CreateParameter(MediaParameter.Previous, ParameterMode.Read, @"VRCOSC/Media/Previous", "Previous", @"Becoming true causes the previous track to play"); ``` -------------------------------- ### Implement VRChat Event Nodes Source: https://context7.com/volcanicarts/vrcosc/llms.txt Create custom nodes that trigger execution flows based on specific VRChat events by implementing INodeEventHandler. ```csharp [Node("On Start", "Events")] public sealed class OnStartNode : Node, INodeEventHandler { public FlowContinuation OnStart = new("On Start"); protected override async Task Process(PulseContext c) { await OnStart.Execute(c); } public Task HandleNodeStart(PulseContext c) => Task.FromResult(true); } [Node("On Instance Joined", "Events")] public sealed class OnInstanceJoinedNode : Node, INodeEventHandler { public FlowContinuation OnInstanceJoined = new(); public ValueOutput WorldId = new("World Id"); protected override async Task Process(PulseContext c) { await OnInstanceJoined.Execute(c); } public Task HandleOnInstanceJoined(PulseContext c, VRChatClientEventInstanceJoined eventArgs) { WorldId.Write(eventArgs.WorldId, c); return Task.FromResult(true); } } [Node("On User Joined", "Events")] public sealed class OnUserJoinedNode : Node, INodeEventHandler { public FlowContinuation OnUserJoined = new(); public ValueOutput User = new("User"); protected override async Task Process(PulseContext c) { await OnUserJoined.Execute(c); } public Task HandleOnUserJoined(PulseContext c, VRChatClientEventUserJoined eventArgs) { User.Write(eventArgs.User, c); return Task.FromResult(true); } } ``` -------------------------------- ### Register and Send OSC Parameters Source: https://context7.com/volcanicarts/vrcosc/llms.txt Register OSC parameters for VRChat with specified types and modes. Use SendParameter to send values and handle incoming parameters via callbacks. ```csharp private enum MyParameter { HeartRate, IsActive, Progress, InputButton } protected override void OnPreLoad() { // Write-only: Send values to VRChat RegisterParameter(MyParameter.HeartRate, "VRCOSC/Health/HeartRate", ParameterMode.Write, "Heart Rate", "Your current heart rate BPM"); RegisterParameter(MyParameter.IsActive, "VRCOSC/Status/Active", ParameterMode.Write, "Is Active", "Whether the feature is currently active"); RegisterParameter(MyParameter.Progress, "VRCOSC/Progress", ParameterMode.Write, "Progress", "Progress value from 0 to 1"); // Read-only: Receive values from VRChat RegisterParameter(MyParameter.InputButton, "VRCOSC/Input/Button", ParameterMode.Read, "Input Button", "Triggered when avatar button is pressed"); } // Send parameters to VRChat private void SendData() { SendParameter(MyParameter.HeartRate, 75); SendParameter(MyParameter.IsActive, true); SendParameter(MyParameter.Progress, 0.5f); // Send any parameter by name directly SendParameter("CustomParam/Value", 42); } // Send and wait for acknowledgment private async Task SendDataAsync() { bool acknowledged = await SendParameterAndWait(MyParameter.HeartRate, 80, blockEvents: true, timeout: TimeSpan.FromSeconds(1)); if (acknowledged) Log("Parameter was acknowledged by VRChat"); } // Handle incoming parameters protected override void OnRegisteredParameterReceived(RegisteredParameter parameter) { switch (parameter.Lookup) { case MyParameter.InputButton: if (parameter.GetValue()) Log("Button pressed!"); break; } } // Handle ANY parameter from VRChat (use sparingly) protected override void OnAnyParameterReceived(VRChatParameter parameter) { Log($"Received parameter: {parameter.Name} = {parameter.Value}"); } ``` -------------------------------- ### Handling Incoming Parameters Source: https://github.com/volcanicarts/vrcosc/wiki/Module-Creation Override these methods to process incoming OSC data. OnAnyParameterReceived should be used sparingly as it captures all incoming parameters. ```c# protected virtual void OnAnyParameterReceived(ReceivedParameter parameter) { } // AvatarModule only protected virtual void OnAvatarModuleReceived(AvatarParameter parameter) { } // WorldModule only protected virtual void OnWorldModuleReceived(WorldParameter parameter) { } ``` -------------------------------- ### Apply ChatBox Formatting Keys Source: https://context7.com/volcanicarts/vrcosc/llms.txt Uses special keys to control line breaks and padding within ChatBox text displays. ```csharp // /n - New line with automatic space padding (maintains ChatBox width) // /v - New line using newline terminator (saves characters, shrinks width) CreateState(MyState.Default, "Status", "Line 1/nLine 2/vLine 3"); // Result: // Line 1 // Line 2 // Line 3 ``` -------------------------------- ### Module Lifecycle Event Handling Source: https://context7.com/volcanicarts/vrcosc/llms.txt Override module lifecycle methods to react to VRChat events such as avatar changes and player status updates. ```csharp protected override Task OnModuleStart() { // Called when modules start (VRChat launched or manual start) // Return false to prevent the module from starting Log("Module starting..."); return Task.FromResult(true); } protected override Task OnModuleStop() { // Called when modules stop (VRChat closed or manual stop) // Good place to clean up resources Log("Module stopping..."); return Task.CompletedTask; } protected override void OnAvatarChange(AvatarConfig? avatarConfig) { // Called when user changes avatar or loads into world if (avatarConfig != null) Log($"Avatar changed to: {avatarConfig.Id}"); } protected override void OnPlayerUpdate() { // Called when player state changes (AFK status, etc.) var player = GetPlayer(); if (player.IsAFK) Log("Player is now AFK"); } ``` -------------------------------- ### Query VRChat Parameters Source: https://context7.com/volcanicarts/vrcosc/llms.txt Retrieve current avatar information, player status, or specific parameter values using OSCQuery. ```csharp // Find a specific parameter value var parameter = await FindParameter("MyParameter"); if (parameter != null) { Log($"Parameter value: {parameter.Value}"); } // Find registered parameter by lookup var registeredParam = await FindParameter(MyParameter.Value); // Get current avatar information var avatar = await FindCurrentAvatar(); if (avatar != null) { Log($"Current avatar: {avatar.Id}"); } // Access player information var player = GetPlayer(); Log($"Is AFK: {player.IsAFK}"); Log($"Is Muted: {player.IsMuted}"); ``` -------------------------------- ### Module Events Source: https://github.com/volcanicarts/vrcosc/wiki/Module-Creation Overview of general and avatar-specific events that modules can hook into. ```APIDOC ## Module Events ### Description Modules provide default events that can be accessed by overriding specific methods. These events are synchronous, and long-running operations should be handled asynchronously using Tasks. ### General Events - **Module Start**: Occurs when VRChat starts or modules are manually started. Ideal for one-time initialization. - Override: `OnModuleStart()` - **Module Stop**: Occurs when VRChat closes or modules are manually stopped. Useful for cleanup and resetting OSC parameters. - Override: `OnModuleStop()` - **Module Update**: Methods marked with the `[ModuleUpdate]` attribute are called at regular intervals. The `ModuleUpdateMode` determines the update frequency and timing. - Attribute: `[ModuleUpdate(ModuleUpdateMode mode)]` - Custom Mode: Allows immediate update and custom update rate. ### Avatar Specific Events - **Avatar Change**: Occurs when a user enters a new avatar or loads into a world. The avatar ID is provided. - Override: `OnAvatarChange(string avatarId)` - Note: This event may not be received if VRC OSC is started after VRChat. - **Player Update**: Called whenever player-related information is updated (e.g., AFK status). - Override: `OnPlayerUpdate()` ### World Specific Events - **World Modules**: Currently not in use. ### Asynchronous Operations - All events are synchronous. For operations taking more than a few microseconds, use asynchronous Tasks to prevent freezing the update thread. ``` -------------------------------- ### Module Metadata Attributes Source: https://github.com/volcanicarts/vrcosc/wiki/Module-Creation Attributes used to define module information, author details, grouping, and documentation. ```csharp [ModuleTitle(string title)] ``` ```csharp [ModuleDescription(string shortDescription, string? longDescription = null)] ``` ```csharp [ModuleAuthor(string name, string? url = null, string? iconUrl = null)] ``` ```csharp [ModuleGroup(ModuleType type)] ``` ```csharp [ModulePrefab(string name, string? url = null) ``` ```csharp [ModuleInfo(string description, string? url = null)] ``` -------------------------------- ### Module Legacy Migration Tag Source: https://github.com/volcanicarts/vrcosc/wiki/Module-Creation Use this attribute to maintain data compatibility if a module class name must be changed. ```csharp [ModuleLegacy("legacymodule")] ``` -------------------------------- ### Module Update Methods with Custom Intervals Source: https://context7.com/volcanicarts/vrcosc/llms.txt Utilize the [ModuleUpdate] attribute to schedule methods for periodic execution. Supports custom intervals and synchronization with the ChatBox system. ```csharp // Custom update rate (default 50ms) [ModuleUpdate(ModuleUpdateMode.Custom)] private void FastUpdate() { // Called every 50ms SendParameter(MyParameter.Value, currentValue); } // Custom interval with immediate execution [ModuleUpdate(ModuleUpdateMode.Custom, updateImmediately: true, deltaMilliseconds: 1000)] private void SlowUpdate() { // Called every 1000ms (1 second), and once immediately on start Log("Periodic update tick"); } // Synchronized with ChatBox evaluation (before ChatBox updates) [ModuleUpdate(ModuleUpdateMode.ChatBox)] private void UpdateChatBox() { // Perfect for setting ChatBox variables right before display SetVariableValue(MyVariable.Status, "Active"); SetVariableValue(MyVariable.Counter, count); } ``` -------------------------------- ### Send OSC Messages Source: https://context7.com/volcanicarts/vrcosc/llms.txt Use SendParameter for standard avatar parameters or access the VRChatOscClient directly for custom addresses. ```csharp // Send avatar parameter by name SendParameter("MyParameter", 1.0f); SendParameter("Toggle", true); SendParameter("Counter", 42); // Access VRChat OSC client directly for special addresses var oscClient = AppManager.GetInstance().VRChatOscClient; // Change avatar oscClient.Send("/avatar/change", "avtr_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"); // Send to any OSC address oscClient.Send("/custom/address", "value"); ``` -------------------------------- ### Create Heart Rate Provider Module Source: https://context7.com/volcanicarts/vrcosc/llms.txt Extend HeartrateModule to integrate external heart rate services. The base class automatically handles standard OSC parameters like BPM and connection status. ```csharp public class PulsoidModule : HeartrateModule { private enum PulsoidSetting { AccessToken } protected override void OnPreLoad() { base.OnPreLoad(); // Creates default heartrate settings and parameters // Add provider-specific settings CreatePasswordTextBox(PulsoidSetting.AccessToken, "Access Token", "Your Pulsoid access token", ""); } protected override PulsoidProvider CreateProvider() { var token = GetSettingValue(PulsoidSetting.AccessToken); return new PulsoidProvider(token); } } ``` -------------------------------- ### Create Custom Pulse Nodes Source: https://context7.com/volcanicarts/vrcosc/llms.txt Extends the Node class to define custom logic with flow inputs/outputs and value connections. ```csharp using VRCOSC.App.Nodes; [Node("My Custom Node", "Custom/Examples")] public sealed class MyCustomNode : Node, IFlowInput { // Flow continuation (execution flow) public FlowContinuation Next = new("Next"); // Value inputs (data received from other nodes) public ValueInput InputText = new("Input Text"); public ValueInput InputNumber = new(); // Value outputs (data sent to other nodes) public ValueOutput OutputResult = new("Result"); protected override async Task Process(PulseContext c) { // Read input values var text = InputText.Read(c); var number = InputNumber.Read(c); // Process data var result = $"{text}: {number}"; // Write output values OutputResult.Write(result, c); // Continue execution flow await Next.Execute(c); } } ``` -------------------------------- ### RegisterParameter Source: https://context7.com/volcanicarts/vrcosc/llms.txt Registers an OSC parameter to send or receive data from VRChat avatars. ```APIDOC ## RegisterParameter ### Description Registers a parameter with a specific type and mode (Read, Write, or ReadWrite) to sync with VRChat. ### Parameters - **enumKey** (Enum) - Required - The internal identifier for the parameter. - **oscAddress** (string) - Required - The OSC address path (e.g., "VRCOSC/Health/HeartRate"). - **mode** (ParameterMode) - Required - The mode of operation (Read, Write, ReadWrite). - **displayName** (string) - Required - Human-readable name. - **description** (string) - Required - Detailed description of the parameter. ``` -------------------------------- ### Module Persistence with [ModulePersistent] Source: https://context7.com/volcanicarts/vrcosc/llms.txt Employ the [ModulePersistent] attribute to automatically save and restore property values across module restarts. Supports various data types. ```csharp public class CounterModule : Module { // This value persists across module restarts [ModulePersistent("totalCount")] private int TotalCount { get; set; } [ModulePersistent("lastRunTime")] private DateTimeOffset LastRunTime { get; set; } [ModulePersistent("userPreferences")] private Dictionary UserPreferences { get; set; } = new(); protected override Task OnModuleStart() { Log($"Module started. Previous count: {TotalCount}, Last run: {LastRunTime}"); TotalCount++; LastRunTime = DateTimeOffset.Now; return Task.FromResult(true); } } ``` -------------------------------- ### ModulePersistent Source: https://context7.com/volcanicarts/vrcosc/llms.txt Automatically saves and restores property values. ```APIDOC ## ModulePersistent ### Description Attribute applied to properties to ensure their values are saved and restored between module restarts. ### Parameters - **key** (string) - Required - The unique key used for storage. ``` -------------------------------- ### SendParameter Source: https://context7.com/volcanicarts/vrcosc/llms.txt Sends a value to VRChat for a registered parameter. ```APIDOC ## SendParameter ### Description Sends a value to VRChat using the registered parameter key or directly by OSC address. ### Parameters - **parameter** (Enum/string) - Required - The parameter identifier or OSC address. - **value** (T) - Required - The value to send (bool, int, or float). ``` -------------------------------- ### Configure VRCOSC Router Source: https://context7.com/volcanicarts/vrcosc/llms.txt Settings for routing OSC data between applications like VRCFaceTracking and VRChat. ```plaintext VRCOSC Router Settings: - Enabled: true - Listen Port: 9001 - Forward Ports: 9000 (VRChat) VRCFaceTracking Settings: - OSC Output Address: 127.0.0.1 - OSC Output Port: 9001 (VRCOSC Router listen port) ``` -------------------------------- ### ModuleUpdate Source: https://context7.com/volcanicarts/vrcosc/llms.txt Defines periodic update methods for modules. ```APIDOC ## ModuleUpdate ### Description Attribute used to mark methods for periodic execution, either at custom intervals or synchronized with the ChatBox system. ### Parameters - **mode** (ModuleUpdateMode) - Required - The update mode (Custom or ChatBox). - **updateImmediately** (bool) - Optional - Whether to execute on start. - **deltaMilliseconds** (int) - Optional - The interval in milliseconds for custom updates. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.