Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions ide/base/client/src/client/client.browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Languages } from '@blockception/ide-shared';
import { LanguageClient, LanguageClientOptions } from 'vscode-languageclient/browser';
import { Manager } from '../manager/manager';
import * as vscode from 'vscode';

export function setupClientBrowser(context: vscode.ExtensionContext): void {
console.log('starting minecraft language client (browser/web worker)');

// Include vscode-vfs scheme used by vscode.dev / github.dev
const clientOptions: LanguageClientOptions = {
documentSelector: [
{ scheme: 'file', language: Languages.McFunctionIdentifier },
{ scheme: 'vscode-vfs', language: Languages.McFunctionIdentifier },
{ scheme: 'file', language: Languages.McLanguageIdentifier },
{ scheme: 'vscode-vfs', language: Languages.McLanguageIdentifier },
{ scheme: 'file', language: Languages.JsonIdentifier },
{ scheme: 'vscode-vfs', language: Languages.JsonIdentifier },
{ scheme: 'file', language: Languages.JsonCIdentifier },
{ scheme: 'vscode-vfs', language: Languages.JsonCIdentifier },
{ scheme: 'file', language: Languages.McProjectIdentifier },
{ scheme: 'vscode-vfs', language: Languages.McProjectIdentifier },
{ scheme: 'file', language: Languages.McMolangIdentifier },
{ scheme: 'vscode-vfs', language: Languages.McMolangIdentifier },
],
};

// Use Uri.joinPath on context.extensionUri — NOT context.asAbsolutePath —
// because asAbsolutePath is not available in the browser extension host.
const serverUri = vscode.Uri.joinPath(context.extensionUri, 'lsp', 'server.browser.js');
const worker = new Worker(serverUri.toString(/* skipEncoding= */ true));

Manager.Client = new LanguageClient(
'languageBlockceptionMinecraftClient',
'LSP-BC Minecraft',
clientOptions,
worker,
);

Manager.Client.start().then(() => {
vscode.commands.executeCommand('setContext', 'ext:is_active', true);
});
}
1 change: 1 addition & 0 deletions ide/base/client/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './client';
export * from './client/client.browser';
export * from './code';
export * from './commands';
export * from './console';
Expand Down
1 change: 1 addition & 0 deletions ide/base/server/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './lsp/server/setup';
export * from './lsp/server/setup.browser';
Comment on lines 1 to +2
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Importing setupServerBrowser from bc-minecraft-lsp goes through ide/base/server/src/index.ts, which now re-exports the Node setupServer module as well. That causes the browser server bundle to pull in vscode-languageserver/node (and other Node-only dependencies) even though only the browser setup is needed. Expose a separate browser-only entry/module (or conditional exports) so the web worker bundle never imports the Node setup path.

Suggested change
export * from './lsp/server/setup';
export * from './lsp/server/setup.browser';
export * from './lsp/server/setup.browser';

Copilot uses AI. Check for mistakes.
13 changes: 13 additions & 0 deletions ide/base/server/src/lsp/server/setup.browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Browser-specific server setup — uses vscode-languageserver/browser
// instead of vscode-languageserver/node.
import { BrowserMessageReader, BrowserMessageWriter, createConnection, ProposedFeatures } from 'vscode-languageserver/browser';
import { LSPConfig } from '../config/config';
import { setupServerCore } from './setup.core';

export function setupServerBrowser(config: LSPConfig): void {
// self is the DedicatedWorkerGlobalScope inside the Web Worker
const messageReader = new BrowserMessageReader(self as DedicatedWorkerGlobalScope);
const messageWriter = new BrowserMessageWriter(self as DedicatedWorkerGlobalScope);
const connection = createConnection(ProposedFeatures.all, messageReader, messageWriter);
setupServerCore(connection, config);
}
115 changes: 115 additions & 0 deletions ide/base/server/src/lsp/server/setup.core.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { Connection, BulkRegistration, InitializeResult } from 'vscode-languageserver';

import { CodeActionService } from '../code-action/service';
import { CodeLensService } from '../code-lens/service';
import { CommandService } from '../commands/service';
import { DataSetService } from '../dataset/service';
import { CompletionService } from '../completion/service';
import { ConfigurationService } from '../configuration/service';
import { Database } from '../database/database';
import { DiagnoserService } from '../diagnostics/service';
import { DocumentManager, IDocumentManager } from '../documents/manager';
import { ExtensionContext } from '../extension';
import { FormatService } from '../format/service';
import { ExtendedLogger } from '../logger/logger';
import { DocumentProcessor, PackProcessor, WorkspaceProcessor } from '../process';
import { DefinitionService, ImplementationService, ReferenceService, TypeDefinitionService } from '../references';
import { SemanticsServer } from '../semantics/service';
import { CapabilityBuilder } from '../services/capabilities';
import { ServiceManager } from '../services/collection';
import { SignatureService } from '../signatures/service';
import { DocumentSymbolService } from '../symbols/document-service';
import { WorkspaceSymbolService } from '../symbols/workspace-service';
import { LSPConfig } from '../config/config';

export function setupServerCore(connection: Connection, config: LSPConfig): void {
const logger = new ExtendedLogger(connection.console);
const manager = new ServiceManager(logger);
const extension = new ExtensionContext(config, connection, manager, logger, {} as IDocumentManager, {} as Database);
const documents = new DocumentManager(logger, extension);
const database = new Database(logger, documents);
extension.documents = documents;
extension.database = database;

const diagnoserService = new DiagnoserService(logger, extension, documents);
const documentProcessor = new DocumentProcessor(logger, extension, diagnoserService);
const packProcessor = new PackProcessor(logger, extension, documentProcessor);
const workspaceProcessor = new WorkspaceProcessor(logger, extension, packProcessor);

manager
// Essentials
.add(new ConfigurationService(logger, extension), documents, database)
// Non Essentials
.add(
diagnoserService,
documentProcessor,
packProcessor,
workspaceProcessor,
new CodeActionService(logger, extension),
new CodeLensService(logger, extension),
new CommandService(logger, extension),
new DataSetService(logger, extension),
new CompletionService(logger, extension),
new DefinitionService(logger, extension),
new DocumentSymbolService(logger, extension),
new FormatService(logger, extension),
new ImplementationService(logger, extension),
new ReferenceService(logger, extension),
new SemanticsServer(logger, extension),
new SignatureService(logger, extension),
new TypeDefinitionService(logger, extension),
new WorkspaceSymbolService(logger, extension),
);

logger.info('starting minecraft server');

//Initialize
connection.onInitialize((params, token, workDoneProgress) => {
workDoneProgress.begin('initializing', 0);

logger.info('Initializing minecraft server', { version: config.version });
const result: InitializeResult = {
serverInfo: {
name: 'bc-minecraft-language-server',
version: config.version,
},
capabilities: {},
};
const builder = new CapabilityBuilder(result.capabilities);

extension.parseClientCapabilities(params.capabilities);
manager.onInitialize(builder, params, token, workDoneProgress);

result.capabilities = builder.result();

workDoneProgress.done();
return result;
});

// This handler provides diagnostics
connection.onInitialized(async () => {
logger.info('Initialized minecraft server', { version: config.version });
manager.setupHandlers(connection);

//Registers any follow ups
const register = BulkRegistration.create();
manager.dynamicRegister(register);
await connection.client.register(register);

return manager.start();
});

// On shutdown handler
connection.onShutdown(() => {
logger.info('Shutting down server');
manager.stop();
});

connection.onExit(() => {
logger.info('exiting server');
manager.dispose();
});

// Listen on the connection
connection.listen();
}
116 changes: 4 additions & 112 deletions ide/base/server/src/lsp/server/setup.ts
Original file line number Diff line number Diff line change
@@ -1,118 +1,10 @@
import { BulkRegistration, createConnection, InitializeResult, ProposedFeatures } from 'vscode-languageserver/node';
import { CodeActionService } from '../code-action/service';
import { CodeLensService } from '../code-lens/service';
import { CommandService } from '../commands/service';
import { DataSetService } from '../dataset/service';
import { CompletionService } from '../completion/service';
import { ConfigurationService } from '../configuration/service';
import { Database } from '../database/database';
import { DiagnoserService } from '../diagnostics/service';
import { DocumentManager, IDocumentManager } from '../documents/manager';
import { ExtensionContext } from '../extension';
import { FormatService } from '../format/service';
import { ExtendedLogger } from '../logger/logger';
import { DocumentProcessor, PackProcessor, WorkspaceProcessor } from '../process';
import { DefinitionService, ImplementationService, ReferenceService, TypeDefinitionService } from '../references';
import { SemanticsServer } from '../semantics/service';
import { CapabilityBuilder } from '../services/capabilities';
import { ServiceManager } from '../services/collection';
import { SignatureService } from '../signatures/service';
import { DocumentSymbolService } from '../symbols/document-service';
import { WorkspaceSymbolService } from '../symbols/workspace-service';
import { createConnection, ProposedFeatures } from 'vscode-languageserver/node';
import { LSPConfig } from '../config/config';
import { setupServerCore } from './setup.core';

export function setupServer(config: LSPConfig) {
export function setupServer(config: LSPConfig): void {
// Create a connection for the server, using Node's IPC as a transport.
// Also include all preview / proposed LSP features.
const connection = createConnection(ProposedFeatures.all);

const logger = new ExtendedLogger(connection.console);
const manager = new ServiceManager(logger);
const extension = new ExtensionContext(config, connection, manager, logger, {} as IDocumentManager, {} as Database);
const documents = new DocumentManager(logger, extension);
const database = new Database(logger, documents);
extension.documents = documents;
extension.database = database;

const diagnoserService = new DiagnoserService(logger, extension, documents);
const documentProcessor = new DocumentProcessor(logger, extension, diagnoserService);
const packProcessor = new PackProcessor(logger, extension, documentProcessor);
const workspaceProcessor = new WorkspaceProcessor(logger, extension, packProcessor);

manager
// Essentials
.add(new ConfigurationService(logger, extension), documents, database)
// Non Essentials
.add(
diagnoserService,
documentProcessor,
packProcessor,
workspaceProcessor,
new CodeActionService(logger, extension),
new CodeLensService(logger, extension),
new CommandService(logger, extension),
new DataSetService(logger, extension),
new CompletionService(logger, extension),
new DefinitionService(logger, extension),
new DocumentSymbolService(logger, extension),
new FormatService(logger, extension),
new ImplementationService(logger, extension),
new ReferenceService(logger, extension),
new SemanticsServer(logger, extension),
new SignatureService(logger, extension),
new TypeDefinitionService(logger, extension),
new WorkspaceSymbolService(logger, extension),
);

logger.info('starting minecraft server');

//Initialize
connection.onInitialize((params, token, workDoneProgress) => {
workDoneProgress.begin('initializing', 0);

logger.info('Initializing minecraft server', { version: config.version });
const result: InitializeResult = {
serverInfo: {
name: 'bc-minecraft-language-server',
version: config.version,
},
capabilities: {},
};
const builder = new CapabilityBuilder(result.capabilities);

extension.parseClientCapabilities(params.capabilities);
manager.onInitialize(builder, params, token, workDoneProgress);

result.capabilities = builder.result();

workDoneProgress.done();
return result;
});

// This handler provides diagnostics
connection.onInitialized(async () => {
logger.info('Initialized minecraft server', { version: config.version });
manager.setupHandlers(connection);

//Registers any follow ups
const register = BulkRegistration.create();
manager.dynamicRegister(register);
await connection.client.register(register);

return manager.start();
});

// On shutdown handler
connection.onShutdown(() => {
logger.info('Shutting down server');
manager.stop();
});

connection.onExit(() => {
logger.info('exiting server');
manager.dispose();
});

// Listen on the connection
connection.listen();
setupServerCore(connection, config);
}
14 changes: 10 additions & 4 deletions ide/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
"vscode": "^1.69.2"
},
"extensionKind": [
"workspace"
"workspace",
"web"
],
"devDependencies": {
"@eslint/js": "^10.0.1",
Expand All @@ -59,7 +60,9 @@
"ts-loader": "^9.5.4",
"typescript": "^5.9.2",
"typescript-eslint": "^8.57.2",
"webpack": "^5.105.4"
"webpack": "^5.105.4",
"@vscode/test-web": "^0.0.51",
"path-browserify": "^1.0.1"
},
"dependencies": {
"bc-minecraft-lsp": "*",
Expand Down Expand Up @@ -91,7 +94,9 @@
"prewebpack": "npm run storeversion && npm run cp-schemas",
"webpack:client": "webpack --mode production --config ./webpack.client.js",
"webpack:server": "webpack --mode production --config ./webpack.server.js",
"webpack": "npm run webpack:client && npm run webpack:server"
"webpack": "npm run webpack:client && npm run webpack:server && npm run webpack:browser",
"webpack:browser": "webpack --mode production --config ./webpack.browser.js",
"chrome": "npm run webpack:browser && vscode-test-web --browserType=chromium --extensionDevelopmentPath=. ."
},
"contributes": {
"configuration": [
Expand Down Expand Up @@ -1587,5 +1592,6 @@
]
}
]
}
},
"browser": "./lsp/client.browser.js"
}
14 changes: 14 additions & 0 deletions ide/vscode/src/client.browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as vscode from 'vscode';
import { setupClientBrowser, Manager } from 'bc-minecraft-lsp-client';

export function activate(context: vscode.ExtensionContext): void {
setupClientBrowser(context);
}

export function deactivate(): Thenable<void> | undefined {
console.log('stopping minecraft language client (browser)');
if (!Manager.Client) {
return undefined;
}
return Manager.Client.stop();
}
4 changes: 4 additions & 0 deletions ide/vscode/src/server.browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { setupServerBrowser } from 'bc-minecraft-lsp';
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This imports setupServerBrowser from the bc-minecraft-lsp package root, which (via export *) also brings in the Node server setup and its Node-only dependencies into the web worker bundle. Import from a browser-only entrypoint/module instead (or split the package exports) so webpack doesn’t include vscode-languageserver/node and other Node code in the browser build.

Suggested change
import { setupServerBrowser } from 'bc-minecraft-lsp';
import { setupServerBrowser } from 'bc-minecraft-lsp/browser';

Copilot uses AI. Check for mistakes.
import { Version } from './version';

setupServerBrowser({ version: Version });
Loading
Loading