Second Life VSCode Plugin
Enhance your Second Life scripting workflow with advanced preprocessing and external editing capabilities!

The Second Life External Scripting Extension transforms VS Code into a development environment for Second Life scripts, supporting both LSL (Linden Scripting Language) and SLua (Second Life Lua) with preprocessing capabilities and viewer integration.
Key Features
Script Preprocessing
- Include System: Modular programming with
#include directives (LSL) and require() syntax (SLua)
- Macro Processing: Define constants and function-like macros with
#define
- Conditional Compilation: Code inclusion with
#ifdef, #ifndef, #if, #elif, #else
- Include Guards: Automatic prevention of duplicate file inclusion
- Circular Protection: Detection and prevention of infinite include loops
- Flexible Search Paths: Configurable include directories for organized projects
Real-Time Viewer Integration
- WebSocket Connection: Direct communication with Second Life viewer
- Live Synchronization: Real-time script editing and updates
- External Editing: Edit scripts externally while maintaining viewer session
- Configurable Networking: Customizable WebSocket port and connection settings
- Language Definitions: Automatic download and updating of latest Second Life language definitions
- Compile Error Display: Real-time display of compilation errors from Second Life viewer
- Debug Message Monitoring: Capture and display debug messages from
llOwnerSay() calls and debug channel chat
- In-World Debugging: Monitor script output and debug information directly in VS Code
Cross-Language Support
- LSL (Linden Scripting Language): Full preprocessing with includes, macros, and conditionals
- SLua (Second Life Lua): Modern Lua scripting with
require() module system
- Smart Detection: Automatic language recognition based on file extensions
Installation
From VS Code Marketplace (Coming Soon)
- Open VS Code
- Go to Extensions (Ctrl+Shift+X)
- Search for "Second Life External Scripting"
- Click Install
Manual Installation
- Download the latest
.vsix file from Releases
- Open VS Code
- Press
Ctrl+Shift+P and type "Extensions: Install from VSIX"
- Select the downloaded file
Quick Start
Setting Up Your First Project
- Create a new workspace folder for your Second Life scripts
- Open the folder in VS Code
- Start scripting with preprocessing features!
Basic Include Example (LSL)
Create modular, maintainable scripts:
utils/constants.lsl
#define MAX_AVATARS 10
#define CHAT_CHANNEL 42
#define DEBUG_MODE
utils/helpers.lsl
#include "constants.lsl"
#ifdef DEBUG_MODE
#define DEBUG_SAY(msg) llOwnerSay("[DEBUG] " + msg)
#else
#define DEBUG_SAY(msg) // No debug output in release
#endif
string formatMessage(string message) {
return "[" + llGetScriptName() + "] " + message;
}
main.lsl
#include "utils/helpers.lsl"
default {
state_entry() {
DEBUG_SAY("Script initialized");
llSay(PUBLIC_CHANNEL, formatMessage("Hello, world!"));
llListen(CHAT_CHANNEL, "", NULL_KEY, "");
}
listen(integer channel, string name, key id, string message) {
if (channel == CHAT_CHANNEL) {
DEBUG_SAY("Received: " + message);
// Process command...
}
}
}
Modern Module System (SLua)
Use modern Lua module patterns:
modules/math-utils.luau
local function clamp(value, min, max)
return math.max(min, math.min(max, value))
end
local function lerp(a, b, t)
return a + (b - a) * clamp(t, 0, 1)
end
return {
clamp = clamp,
lerp = lerp
}
main.luau
local mathUtils = require("modules/math-utils")
function onTouch(avatar)
local distance = (avatar.position - object.position).magnitude
local alpha = mathUtils.lerp(0.2, 1.0, distance / 10.0)
object:setAlpha(alpha)
end
Configuration
Only use plugin in specific workspaces
The plugin can be configured to only run inside specific workspaces, instead of globally.
To do this, go to settings > extienstions and find the SL Scipting settings,
and uncheck the Enabled setting.
Then in any workspace you want to use the plugin in, you can either manually set the
Enabled setting at the workspace level, or open the command pallete and run the
Second Life: Enable Extension for Workspace command.
Preprocessor Settings
Configure preprocessing behavior in VS Code settings:
{
"slVscodeEdit.preprocessor.enable": true,
"slVscodeEdit.preprocessor.includePaths": [
".",
"./include/",
"**/include/"
],
"slVscodeEdit.preprocessor.maxIncludeDepth": 5
}
Note: The includePaths shown above are the defaults. You can customize them to match your project structure (e.g., add "./lib/", "./utils/", or "**/common/").
Network Settings
Customize viewer connection:
{
"slVscodeEdit.network.websocketPort": 9020,
"slVscodeEdit.network.disconnectDelayMs": 100,
"slVscodeEdit.network.disposeDelayMs": 1000
}
Storage Settings
Control where configuration files are stored:
{
"slVscodeEdit.storage.useLocalConfig": true
}
When true (default), configuration files are stored in your workspace's .vscode directory. When false, they're stored in the global VS Code settings directory.
Using with Second Life Viewer
Connection Setup
- Enable External Script Editor in Second Life viewer preferences
- Set the editor to connect via WebSocket on port 9020 (configurable)
- Configure the extension using VS Code settings for WebSocket connection
Workflow
- Right-click on an object in Second Life
- Select "Edit" → "Scripts"
- Click "New Script" or "Edit" on existing script
- Choose external editor - VS Code will automatically open
- Edit in VS Code with full preprocessing support
- Save to sync changes back to the viewer
Linux-specific instructions
If using the flatpak version of vscode, the External Script Editor command is:
/usr/bin/flatpak run --file-forwarding com.visualstudio.code --reuse-window @@ "%s" @@
Additional Features
Conditional Compilation
Create feature-toggled and platform-specific code:
// Feature flags
#define FEATURE_ANALYTICS
#define FEATURE_ADVANCED_PHYSICS
// #define FEATURE_BETA_FEATURES
// Environment configuration
#ifdef PRODUCTION
#define LOG_LEVEL 1
#define MAX_RETRIES 3
#else
#define LOG_LEVEL 3
#define MAX_RETRIES 10
#endif
default {
state_entry() {
llOwnerSay("Log level: " + (string)LOG_LEVEL);
#ifdef FEATURE_ANALYTICS
// Analytics code only included when feature is enabled
initializeAnalytics();
#endif
#ifdef FEATURE_BETA_FEATURES
llOwnerSay("Beta features enabled");
#endif
}
}
Function-Like Macros
Create reusable code templates:
// Define a logging macro with parameters
#define LOG_ERROR(category, message) \
llOwnerSay("[ERROR][" + category + "] " + message + " at " + (string)llGetUnixTime())
#define VALIDATE_AVATAR(id, action) \
if (id == NULL_KEY) { \
LOG_ERROR("AVATAR", "Invalid avatar ID in " + action); \
return; \
}
default {
touch_start(integer total_number) {
key toucher = llDetectedKey(0);
VALIDATE_AVATAR(toucher, "touch_start");
// Macro expands to full validation and logging code
LOG_ERROR("TOUCH", "Unexpected touch event");
}
}
Nested Requirements (SLua)
Build complex module hierarchies:
utils/logger.luau
local Logger = {}
function Logger.info(message)
print("[INFO] " .. message)
end
function Logger.warn(message)
print("[WARN] " .. message)
end
function Logger.error(message)
print("[ERROR] " .. message)
end
return Logger
services/inventory.luau
local logger = require("utils/logger")
local function getItemCount(itemName)
logger.info("Checking inventory for: " .. itemName)
-- Inventory logic here
return 5
end
local function addItem(itemName, count)
logger.info("Adding " .. count .. " of " .. itemName)
-- Add item logic here
end
return {
getItemCount = getItemCount,
addItem = addItem
}
main.luau
local inventory = require("services/inventory")
function onTouch(avatar)
local coinCount = inventory.getItemCount("coins")
inventory.addItem("coins", 1)
end
Commands
Access these commands via the Command Palette (Ctrl+Shift+P):
| Command |
Description |
Second Life: Force Language Update |
Refresh language definitions and features |
Documentation
Comprehensive guides available in the doc/ directory:
Requirements
- Visual Studio Code 1.85.0 or later
- Node.js (for development and testing)
- Second Life Viewer with external editor support
Recommended Extensions
For enhanced language support and features, install these language server extensions:
For SLua/Luau files:
- Selene (
kampfkarren.selene-vscode) - Lua linter and language support
- Luau Language Server (
johnnymorganz.luau-lsp) - Luau language server
For LSL files:
- LSL Language Server (such as
sekkmer.vscode-lsl-lsp) - LSL language support with diagnostics
Additional Extensions for Enhanced Development:
- StyLua (
johnnymorganz.stylua) - Lua code formatter
- VSCode LSL (
vrtlabs.vscode-lsl) - Alternative LSL language support
Note: These extensions are optional but recommended for the best development experience. The preprocessor and viewer integration features work independently of these language servers.
Troubleshooting
Common Issues
WebSocket Connection Failed
- Check port: Ensure port 9020 (or configured port) is available
- Firewall: Allow VS Code through Windows Firewall
- Viewer settings: Verify external editor is enabled in viewer preferences
Include Files Not Found
- Check paths: Verify include paths in settings
- File extensions: Ensure
.lsl or .luau extensions are used
- Working directory: Includes are resolved relative to workspace root
Preprocessing Not Working
- Enable preprocessing: Check
slVscodeEdit.preprocessor.enable setting
- File types: Preprocessing only works on
.lsl and .luau files
- Syntax errors: Check for malformed directive syntax
Getting Help
Contributing
We welcome contributions! Please see our contributing guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature)
- Commit your changes (
git commit -m 'Add amazing feature')
- Push to the branch (
git push origin feature/amazing-feature)
- Open a Pull Request
Development Setup
git clone https://github.com/secondlife/sl-vscode-plugin.git
cd sl-vscode-plugin
npm install
npm run compile
Running Tests
npm test # Full test suite
npm run test-unit # Unit tests only
npm run lint # Code linting
License
This project is licensed under the MIT License - see the LICENSE file for details.
Version History
v1.0.1
- Fix for incorrect luau-lsp config use
- Switch from class to extern syntax for luau-lsp defs and move DetecteEvent
- Fix selene yaml gen and toml config
- Fix for selene yaml self on : calls
- Fix default data to have eventname for LLEvents:off
- Make saves of included/required files trigger 'saves' on actively sync'd file
- Fix precomp require generating invalid code for files with no trailing line ending
- Add fallback lookup for matching file, if the default glob finds nothing
- Add config to enable/disable the extension, and a command to do it quickly
- Update Package Name Across Project to fix README Links and be Consistent with Repo Name
- Implement optional check to prevent saving over a file with identicle content
v1.0.0 (Initial Release)
- Advanced LSL and SLua preprocessing
- WebSocket viewer integration
- Include system with search paths
- Macro processing and conditional compilation
- Include guards and circular protection
- Real-time script synchronization