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.
- Include System: Modular programming with
#includedirectives (LSL) andrequire()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
- 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
- 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
- Open VS Code
- Go to Extensions (Ctrl+Shift+X)
- Search for "Second Life External Scripting"
- Click Install
- Download the latest
.vsixfile from Releases - Open VS Code
- Press
Ctrl+Shift+Pand type "Extensions: Install from VSIX" - Select the downloaded file
- Create a new workspace folder for your Second Life scripts
- Open the folder in VS Code
- Start scripting with preprocessing features!
Create modular, maintainable scripts:
utils/constants.lsl
#define MAX_AVATARS 10
#define CHAT_CHANNEL 42
#define DEBUG_MODEutils/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...
}
}
}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)
endThe 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.
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/").
Customize viewer connection:
{
"slVscodeEdit.network.websocketPort": 9020,
"slVscodeEdit.network.disconnectDelayMs": 100,
"slVscodeEdit.network.disposeDelayMs": 1000
}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.
- 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
- 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
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
}
}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");
}
}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 Loggerservices/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)
endAccess these commands via the Command Palette (Ctrl+Shift+P):
| Command | Description |
|---|---|
Second Life: Force Language Update |
Refresh language definitions and features |
Comprehensive guides available in the doc/ directory:
- Preprocessor Guide - Complete preprocessing reference
- Message Interfaces - WebSocket communication protocols
- Visual Studio Code 1.85.0 or later
- Node.js (for development and testing)
- Second Life Viewer with external editor support
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.
- 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
- Check paths: Verify include paths in settings
- File extensions: Ensure
.lslor.luauextensions are used - Working directory: Includes are resolved relative to workspace root
- Enable preprocessing: Check
slVscodeEdit.preprocessor.enablesetting - File types: Preprocessing only works on
.lsland.luaufiles - Syntax errors: Check for malformed directive syntax
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: Check the
doc/folder for detailed guides
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
git clone https://github.com/secondlife/sl-vscode-plugin.git
cd sl-vscode-plugin
npm install
npm run compilenpm test # Full test suite
npm run test-unit # Unit tests only
npm run lint # Code lintingThis project is licensed under the MIT License - see the LICENSE file for details.
- 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
- 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