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)
endConfigure 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")
-- Logger is automatically available through nested require
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.
- 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